diff --git a/README.md b/README.md index b940e2f..a87ff96 100644 --- a/README.md +++ b/README.md @@ -1,178 +1,226 @@ # bps-schema -多尺度多性能协同数据模型。 +建筑性能模拟数据模型。所有类型定义以 draft-2020-12 标准 JSON Schema 为准。 -## 仓库文件 +## 文件架构 -| 文件 | 说明 | -|------|------| -| `schema-building.json` | 建筑几何 + 核心实体(Building, Floor, Room, Aperture, Boundary, Element, Shaft 等) | -| `schema-energy.json` | 能耗模拟领域(Material, Construction, RoomProgram, Schedule 等) | +采用"尺度 × 模拟域"二维分文件架构。每个尺度按几何和模拟域拆分为独立文件。 -## Schema 规则 +### 建筑单体尺度 -### 1. JSON 为唯一真理源 +| 文件 | $id | defs | 说明 | +|------|-----|------|------| +| `schema-building.json` | bps/building | 30 | 建筑几何实体,对齐 HBJSON 几何层级 | +| `schema-energy.json` | bps/energy | 49 | EnergyPlus 能耗模拟参数 | +| `schema-radiance.json` | bps/radiance | 25 | Radiance 采光模拟参数 | +| `schema-cfd.json` | bps/cfd | 14 | CFD 建筑风环境模拟参数(AI 生成的示例文件,需人工审核后使用) | -所有类型定义以 JSON 文件为准。TypeScript / Python 等语言的绑定代码均从 JSON 生成,不得手工维护。 +### 社区尺度 -### 2. 不保存派生数据 +| 文件 | $id | defs | 说明 | +|------|-----|------|------| +| `schema-community.json` | bps/community | 7 | 社区几何:Site / Terrain / Road / GreenSpace / WaterBody(AI 生成的示例文件,需人工审核后使用) | +| `schema-community-energy.json` | bps/community-energy | 8 | 区域能源:Plant / Network / Pipe / BuildingConnection(AI 生成的示例文件,需人工审核后使用) | +| `schema-community-cfd.json` | bps/community-cfd | 13 | 社区风环境:计算域 / 网格 / 湍流 / 边界条件 / 求解器(AI 生成的示例文件,需人工审核后使用) | +| `schema-community-microclimate.json` | bps/community-microclimate | 2 | 微气候:UHI 强度 / 风速修正 / 地表反照率(AI 生成的示例文件,需人工审核后使用) | -Schema 只保存**原始定义数据**,不包含任何可从已有字段计算得出的值。 +### 城市尺度 -``` -❌ area — 可由 region 计算 -❌ volume — 可由 region + height 计算 -❌ boundingBox — 可由子实体几何计算 -✅ region — 房间轮廓点集 -✅ height — 房间高度 -``` +| 文件 | $id | defs | 说明 | +|------|-----|------|------| +| `schema-urban.json` | bps/urban | 3 | 城市几何:ClimateZone / LandUse(AI 生成的示例文件,需人工审核后使用) | +| `schema-urban-energy.json` | bps/urban-energy | 5 | 城市能源:需求聚合 / 可再生能源潜力 / 碳平衡(AI 生成的示例文件,需人工审核后使用) | +| `schema-urban-cfd.json` | bps/urban-cfd | 15 | 城市风环境:行人高度评估 / 街道峡谷 / 风舒适标准(AI 生成的示例文件,需人工审核后使用) | -### 3. 字段命名 +### 聚合入口 -| 规则 | 示例 | -|------|------| -| 使用 camelCase | `siteBasePoint`, `sillHeight`, `openRatio` | -| 避免缩写(广为人知的除外) | `identifier` 而非 `id`, `displayName` 而非 `name` | -| 布尔值用正面语义 | `operable` 而非 `nonOperable` | -| 枚举值用 snake_case | `exterior_wall`, `curtain_wall` | +| 文件 | $id | defs | 说明 | +|------|-----|------|------| +| `schema-all.json` | bps/all | 11 | 引用以上所有文件,提供完整验证入口 | -### 4. 类型系统 +**合计**:11 个领域文件 + 1 个聚合文件,171 个类型定义。 -**基础类型:** -- `string` — 字符串 -- `number` — 浮点数 -- `integer` — 整数 -- `boolean` — 布尔值 -- `object` — 任意对象 +## Schema 规范 -**复合类型:** -- `TypeName[]` — 数组,如 `Polyline3d` 的 `points` 字段类型为 `Point3d[]` -- `TypeName` — 引用自定义类型或实体 +所有文件均遵循 [JSON Schema draft-2020-12](https://json-schema.org/draft/2020-12/release-notes): -**自定义类型**定义在 `types` 段,描述纯数据结构,不是业务实体。例如 `Point3d`(三维点)、`Polyline3d`(多段线)、`TimePoint`(时刻点)。 +- `$defs` — 所有类型、枚举、实体的定义区 +- `$ref` — 类型引用,使用 JSON Schema 标准 `$ref` 机制 +- `oneOf` — 判别联合体(如边界条件的 5 种类型) +- `allOf` — 实体组合(`_IdentifiedObject` + 具体属性) +- `const` / `enum` — 类型判别字段和枚举值 +- `required` — 必填字段 +- `default` — 缺省值 +- `minimum` / `maximum` / `exclusiveMinimum` — 数值约束 +- `pattern` / `minLength` / `maxLength` — 字符串约束 +- `additionalProperties: false` — 严格模式,禁止额外字段 -### 5. 实体结构 +## schema-building.json:建筑几何 -```json -"EntityName": { - "description": "中文说明", - "tags": { "scale": ["building"], "simulation": ["energy"] }, - "attributes": { - "fieldName": { - "type": "string", - "required": true, - "unit": "m", - "default": 0, - "description": "字段说明", - "tags": { "scale": ["building"], "simulation": ["energy", "daylight"] } - } - }, - "children": { - "childName": { - "type": "ChildEntity", - "multiple": true, - "description": "子实体说明" - } - } -} -``` +对齐 [honeybee-schema](https://github.com/ladybug-tools/honeybee-schema) 几何层级,覆盖 Model → Room → Face → Aperture/Door → Shade 层级。 -- `attributes` — 标量字段(string, number, boolean, enum, 自定义类型) -- `children` — 关联的子实体(1:1 或 1:N) -- `required: true` — 必填字段,序列化时必须存在 -- `default` — 缺省值(可选字段未提供时使用) -- `unit` — 单位标注(仅文档用途) +### 几何原语 -### 6. 判别联合体(Discriminated Union) +- `Point3D` — 三维坐标 (x, y, z) +- `Face3D` — 平面多边形(boundary + holes + plane) +- `Mesh3D` — 三角/四边形网格(vertices + faces + colors) +- `Plane` — 平面(法线 n + 原点 o + x 轴) +- `Color` — RGBA 颜色 -当一个实体存在多种形态时,使用 `variants` 表达: +### 边界条件 -```json -"Room": { - "discriminator": "creationMethod", - "variants": { - "planar_extrude": { ... }, - "mass_slice": { ... }, - "manual": { ... } - } -} -``` +- `Outdoors` / `Surface` / `Ground` / `Adiabatic` / `OtherSideTemperature` +- Aperture/Door 仅支持 Outdoors 和 Surface 两种 -不同变体可包含不同的必填字段。判别字段的值决定了使用哪个变体。当前使用判别联合体的实体: -- `Room` — 判别字段 `creationMethod`,变体:`planar_extrude`、`mass_slice`、`manual` -- `Aperture` — 判别字段 `sourceType`,变体:`hosted`、`declarative` +### 标识符规范 -### 7. 枚举 +- `identifier`:`^[.A-Za-z0-9_-]+$`,1-100 字符 +- `display_name`:无限制(仅用于 UI 展示) +- `user_data`:可选字典 -枚举定义在 `enums` 段,每个枚举列出所有允许值。 +## schema-energy.json:能耗模拟参数 -### 8. 尺度与模拟类型标签(tags) +覆盖 HBJSON energy properties 核心实体:材料、构造、时间表、负荷、HVAC、构造集、程序类型。 -每个字段可标注两个维度的标签: +### 材料 -**尺度(scale):** -| 标签 | 说明 | -|------|------| -| `building` | 建筑尺度 | -| `community` | 社区/街区尺度 | -| `urban` | 城市尺度 | +- `EnergyMaterial` — 有质量材料 +- `EnergyMaterialNoMass` — 无质量材料 +- `EnergyMaterialVegetation` — 植被材料 +- `EnergyWindowMaterialGlazing` / `Gas` / `GasCustom` / `GasMixture` / `SimpleGlazSys` — 窗材料 +- `EnergyWindowMaterialBlind` / `Shade` — 百叶/遮阳 +- `EnergyWindowFrame` — 窗框 -**模拟类型(simulation):** -| 标签 | 说明 | -|------|------| -| `energy` | 能耗模拟 | -| `daylight` | 采光分析 | -| `solar` | 日照分析 | -| `thermal_comfort` | 热舒适分析 | -| `carbon` | 碳排放核算 | -| `wind` | 风环境模拟 | -| `general` | 通用(不特定于某种模拟) | +### 构造 -标签用于快速筛选特定尺度或某类模拟分析所需的字段。例如: +- `OpaqueConstruction` / `WindowConstruction` / `AirBoundaryConstruction` / `ShadeConstruction` +- 各自 Abridged 版本(identifier 引用) +- `WindowConstructionShade` / `WindowConstructionDynamic` — 含动态遮阳的窗构造 -```json -"northAngle": { - "type": "number", - "tags": { "simulation": ["energy", "daylight", "solar", "thermal_comfort", "wind"] } -} -``` +### 时间表 -表示 `northAngle` 对能耗、采光、日照、热舒适、风环境模拟均有影响。 +- `ScheduleTypeLimit` / `ScheduleDay` / `ScheduleFixedInterval` / `ScheduleRulesetAbridged` / `ScheduleRule` -```json -"embodiedCarbon": { - "type": "number", - "tags": { "scale": ["building", "community", "urban"], "simulation": ["carbon"] } -} -``` +### 负荷与设定值 -表示 `embodiedCarbon` 适用于建筑/社区/城市三个尺度,仅用于碳排放核算。 +- `PeopleAbridged` / `LightingAbridged` / `ElectricEquipmentAbridged` / `GasEquipmentAbridged` +- `ServiceHotWaterAbridged` / `InfiltrationAbridged` / `VentilationAbridged` +- `SetpointAbridged` / `InternalMassAbridged` / `ProcessAbridged` -### 9. 只描述数据本身 +### 程序类型 / 构造集 / HVAC -Schema 只描述**建筑数据本身**,不描述数据的生成方式。 +- `ProgramTypeAbridged` / `ConstructionSetAbridged` +- `DefaultProgramTypesAbridged` / `DefaultConstructionSetAbridged` +- `IdealAirSystemAbridged` + +## schema-radiance.json:采光模拟参数 + +兼容 HBJSON radiance properties,覆盖 Radiance 材质、构造集、传感器网格、视角。 + +### 材质(Modifiers) + +- `Plastic` — 塑料材质(RGB 反射率 + 镜面度 + 粗糙度) +- `Metal` — 金属材质(继承 Plastic,镜面度默认 0.9) +- `Trans` — 半透明材质(透射漫反射比 + 透射镜面比) +- `Glass` — 玻璃材质(RGB 透射率 + 折射率) +- `Mirror` — 镜面材质(RGB 反射率) +- `Light` / `Glow` — 发光材质(RGB 发射率) +- `BSDF` — 双向散射分布函数材质(BSDF XML 数据 + 朝向) +- `Void` — 空材质 + +### 材质集(Modifier Sets) + +- `WallModifierSetAbridged` / `FloorModifierSetAbridged` / `RoofCeilingModifierSetAbridged` +- `ApertureModifierSetAbridged` / `DoorModifierSetAbridged` / `ShadeModifierSetAbridged` +- `ModifierSet` — 材质集聚合 + +### 传感器与视角 + +- `Sensor` / `SensorGrid` — 传感器网格 +- `View` — Radiance 视角(6 种视角类型) + +## schema-cfd.json:CFD 风环境模拟 + +独立领域(非 HBJSON),覆盖 CFD 建筑风环境分析的完整参数体系。 + +### 核心参数 + +- `WindProfile` — 风剖面(4 种剖面 + 地形类别 + 风向) +- `CFDDomain` — 计算域定义 +- `MeshParameters` — 网格设置(基础网格 + 局部加密 + 壁面层) +- `TurbulenceParameters` — 湍流设置(6 种模型 + 壁面函数) +- `BoundaryConditions` — 进出口/顶部/侧面/地面/建筑墙面边界类型 +- `SolverSettings` — 求解器设置(稳态/瞬态 + SIMPLE/PISO + 收敛准则) + +## schema-community*.json:社区尺度 + +### 几何(schema-community.json) + +- `Site` — 场地顶级实体,含 2D 边界 +- `TerrainGrid` / `TerrainTIN` — 高程网格或三角网 +- `Road` / `GreenSpace` / `WaterBody` — 基础设施 + +### 区域能源(schema-community-energy.json) + +- `DistrictEnergy` — 区域能源系统顶级实体 +- `Plant` — 源站(CHP / Boiler / HeatPump / Chiller / PV 等) +- `Network` — 管网(CHW / HW / Steam / Electricity) +- `Pipe` / `BuildingConnection` — 管段与建筑接入 + +### 风环境(schema-community-cfd.json) + +- `CFDDomain` — 社区尺度计算域 +- `MeshParameters` — 含局部加密区域 +- `SolverSettings` / `TurbulenceParameters` / `BoundaryConditions` + +## schema-urban*.json:城市尺度 + +### 几何(schema-urban.json) + +- `ClimateZone` — 气候分区(边界 + 气候区代码 + 度日数) +- `LandUse` — 用地性质(边界 + 用地类型 + 容积率 + 建筑密度) + +### 能源(schema-urban-energy.json) + +- `UrbanEnergyDemand` — 各用地类型年度能耗 +- `RenewablePotential` — 屋顶/立面/地面可再生能源潜力 +- `UrbanEnergyBalance` — 城市能源平衡(自给率 / 碳排放 / EUI) + +### 风环境(schema-urban-cfd.json) + +- `UrbanCFDSettings` — 城市级 CFD 设置 +- `WindComfortAssessment` — 行人风舒适评估(Laws / NEN_8100 / COST_732 标准) +- `MeshParameters` — 含行人高度加密层 ## 使用方式 -各项目从 JSON schema 生成对应语言的类型代码: +### 数据验证 ```bash -# TypeScript(示例) -python3 scripts/gen-ts.py schema-building.json > dist/building.d.ts - -# Python Pydantic(示例) -python3 scripts/gen-py.py schema-building.json > archgen_schema/building.py +pip install jsonschema +python3 -c " +import json, jsonschema +with open('schema-building.json') as f: + schema = json.load(f) +with open('model.hbjson') as f: + data = json.load(f) +jsonschema.validate(data, schema) +" ``` -具体生成器暂时不在本仓库维护。 +### TypeScript 类型生成 ---- +```bash +npx quicktype schema-building.json -o dist/building.d.ts --lang typescript +npx quicktype schema-energy.json -o dist/energy.d.ts --lang typescript +npx quicktype schema-radiance.json -o dist/radiance.d.ts --lang typescript +npx quicktype schema-cfd.json -o dist/cfd.d.ts --lang typescript +``` -## TODO +### Python Pydantic 生成 -- [ ] 定义 building / community / urban 每个尺度的最小字段集合 -- [ ] 制定 `required` 与 `default` 的判定规则文档 -- [ ] 梳理影响模拟性能的字段并标注影响等级 -- [ ] 明确"智能优化"的定义和 scope(形态优化 vs 性能目标驱动) -- [ ] 确定优化变量、约束条件在 schema 中的表达方式 -- [ ] 完善 schema 的 tags 系统(如需新增 `minScale` / `maxScale` / `performanceImpact` / `optimizable` 等属性) +```bash +pip install datamodel-code-generator +datamodel-codegen --input schema-building.json --output dist/building.py --output-model-type pydantic_v2.BaseModel +datamodel-codegen --input schema-energy.json --output dist/energy.py --output-model-type pydantic_v2.BaseModel +``` diff --git a/docs/multiscale-hbjson-extension.md b/docs/multiscale-hbjson-extension.md new file mode 100644 index 0000000..264437d --- /dev/null +++ b/docs/multiscale-hbjson-extension.md @@ -0,0 +1,349 @@ +# 基于 HBJSON 扩展多尺度数据模型:方案设计 + +> 日期:2026-05-28 +> 来源:HBJSON Schema 分析与多尺度扩展讨论 + +--- + +## 一、背景 + +HBJSON(Honeybee Schema)是 Ladybug Tools 生态中建筑单体性能模拟的标准数据交换格式。它以 Room → Face → Aperture/Door 的层级结构表达建筑三维几何,并通过 `properties` 扩展点挂载 EnergyPlus/Radiance/DOE-2 的模拟参数。 + +本课题"多尺度绿色性能云端模拟"需要在建筑单体之上,覆盖社区和城市尺度的模拟需求。本文先解读 HBJSON 结构,再分析 Ladybug Tools 现有方案(Dragonfly)的能力与局限,最后提出多尺度扩展方案。 + +--- + +## 二、HBJSON Schema 结构解读 + +### 2.1 整体文件结构 + +HBJSON 是一个自包含的 JSON 文件,由一个顶层 `Model` 对象统领所有数据。文件不依赖外部引用,所有几何、构造、材料、负荷、时间表均内嵌或通过 identifier 引用。 + +### 2.2 顶层 Model 对象 + +`Model` 是文件的根节点,核心字段如下: + +| 字段 | 类型 | 说明 | +|---|---|---| +| `type` | string | 固定为 `"Model"` | +| `version` | string | Schema 版本号,格式 `x.y.z` | +| `rooms[]` | Room[] | 建筑房间列表,每个 Room 是一个封闭三维空间 | +| `orphaned_faces[]` | Face[] | 无父 Room 的面(不可用于能耗模拟导出) | +| `orphaned_apertures[]` | Aperture[] | 无父 Face 的窗 | +| `orphaned_doors[]` | Door[] | 无父 Face 的门 | +| `orphaned_shades[]` | Shade[] | 无父对象的独立遮阳 | +| `shade_meshes[]` | ShadeMesh[] | 网格遮阳(周边建筑、地形) | +| `units` | enum | 几何单位:`Meters` / `Millimeters` / `Feet` / `Inches` / `Centimeters` | +| `tolerance` | float | 顶点容差(米制默认 0.01),用于几何容差检查 | +| `angle_tolerance` | float | 角度容差(默认 1.0 度),用于共线/共面检查 | +| `properties` | ModelProperties | 模型级扩展属性(Energy / Radiance / DOE-2) | + +### 2.3 几何层级与嵌套关系 + +几何对象按严格的层级嵌套: + +``` +Model +├── rooms[] +│ ├── faces[] ← 包围 Room 的面(≥4 个形成封闭体积) +│ │ ├── apertures[] ← 窗(开洞,透光) +│ │ │ ├── indoor_shades[] ← 室内遮阳(窗帘、窗台) +│ │ │ └── outdoor_shades[] ← 室外遮阳(百叶、格栅) +│ │ ├── doors[] ← 门 +│ │ ├── indoor_shades[] +│ │ └── outdoor_shades[] ← 室外遮阳(阳台、挑檐) +│ ├── indoor_shades[] ← 室内家具/隔断 +│ └── outdoor_shades[] ← 室外树木/景观 +└── shade_meshes[] ← 独立网格遮阳 +``` + +各对象核心字段: +- `Room`:`faces[]`(面列表)、`multiplier`(标准层复用系数)、`zone`(热区标识)、`story`(楼层标识)、`exclude_floor_area`(是否排除楼板面积) +- `Face`:`face_type`(`Wall` / `Floor` / `RoofCeiling` / `AirBoundary`)、`boundary_condition`(边界条件) +- `Aperture` / `Door`:`is_operable`(可开启)、`is_glass`(玻璃门) +- `Shade`:`is_detached`(是否脱离主体) + +### 2.4 几何原语 + +所有 3D 几何基于以下原语构建: + +**Point3D**:三维坐标点 +```json +{ "type": "Point3D", "x": 0.0, "y": 0.0, "z": 0.0 } +``` + +**Face3D**:平面多边形(Face/Aperture/Door 的几何基础) +```json +{ + "type": "Face3D", + "boundary": [[x,y,z], [x,y,z], ...], // 外轮廓顶点,≥3 个 + "holes": [[...], ...], // 孔洞轮廓(可选) + "plane": { "n": [0,0,1], "o": [0,0,0] } // 法线 + 原点(可选,自动推导) +} +``` + +**Mesh3D**:三角/四边形网格(ShadeMesh 的几何基础) +```json +{ + "type": "Mesh3D", + "vertices": [[x,y,z], ...], // 顶点池 + "faces": [[0,1,2], [1,3,2]], // 面索引(3 或 4 个索引) + "colors": [{ "r":255, "g":0, "b":0, "a":255 }] // 顶点/面着色(可选) +} +``` + +### 2.5 边界条件(Boundary Conditions) + +Face 的 `boundary_condition` 字段定义面与外部环境的关系,共 5 种类型: + +| 类型 | 适用场景 | 核心参数 | +|---|---|---| +| `Outdoors` | 外表面暴露于室外 | `sun_exposure`、`wind_exposure`、`view_factor`(对地视角系数) | +| `Surface` | 与另一表面对接 | `boundary_condition_objects`(相邻对象 identifier 列表,Face 为 2 个,SubFace 为 3 个) | +| `Ground` | 接地面 | 无附加参数 | +| `Adiabatic` | 绝热面(相邻空间温湿度相同) | 无附加参数 | +| `OtherSideTemperature` | 给定外侧温度边界 | `heat_transfer_coefficient`(W/m²K)、`temperature`(℃) | + +约束:`AirBoundary` 类型的 Face **必须**有 `Surface` 边界条件,校验器会强制检查。 + +### 2.6 Abridged(简写)模式 + +HBJSON 的核心设计特征。每个 properties 对象均有两种形态: + +| 模式 | 结构 | 用途 | +|---|---|---| +| `XXXProperties` | 内嵌完整对象(含所有 Material、Construction 定义) | 运行时内存对象 | +| `XXXPropertiesAbridged` | 仅存 identifier 字符串引用 | 序列化到 JSON 文件 | + +工作机制: +``` +Room.properties.energy.construction_set: "Generic2005Construction" + │ + ▼ +Model.properties.energy.construction_sets: [ + { "identifier": "Generic2005Construction", + "wall_construction": "WallCons_Generic", ... } +] +Model.properties.energy.constructions: [ + { "identifier": "WallCons_Generic", "layers": ["mat_1", "mat_2"] } +] +Model.properties.energy.materials: [ + { "identifier": "mat_1", "type": "EnergyMaterial", ... } +] +``` + +这种"外键引用"模式避免了几何层级的循环嵌套,大幅减小文件体积,是处理大型建筑模型的关键优化。 + +### 2.7 扩展属性系统(Properties Extension) + +每个几何层级都通过 `properties` 字段挂载多引擎数据,采用插件式架构: + +``` +properties: +├── energy — EnergyPlus(构造、负荷、HVAC、时间表) +├── radiance — Radiance(材质、动态遮阳状态、传感器网格) +└── doe2 — DOE-2(历史兼容) +``` + +各层级的 Energy 属性举例: +- `Model` 级:`constructions[]`、`materials[]`、`programs[]`(使用模式)、`schedules[]`、`hvacs[]` +- `Room` 级:`construction_set`(引用)、`program_type`(引用)、`hvac`(引用)、`shw`(引用),以及逐条覆盖的 `people`、`lighting`、`equipment`、`infiltration`、`ventilation`、`setpoint` +- `Face` 级:`construction`(引用)、`vent_crack`(AirflowNetwork 裂缝) +- `Aperture` 级:`construction`(引用)、`vent_opening` +- `Shade` 级:`construction`(引用)、`transmittance_schedule`(透射率时间表)、`pv_properties`(光伏) + +### 2.8 标识符与元数据 + +所有对象继承 `IDdBaseModel`,统一标识规范: + +| 字段 | 约束 | 说明 | +|---|---|---| +| `identifier` | `^[.A-Za-z0-9_-]+$`,1-100 字符 | 唯一标识,序列化/引用/跨引擎传递均使用此字段 | +| `display_name` | 无限制 | 仅用于 UI 展示,可含中文、空格、特殊字符 | +| `user_data` | 可选字典 | 用户自定义附加数据,键值需为基本类型 | + +### 2.9 容差机制 + +HBJSON 通过两个参数处理 CAD 几何导入时的浮点误差: + +- `tolerance`(距离容差):顶点坐标差值小于此值视为重合,用于封闭体积检查、法线校正 +- `angle_tolerance`(角度容差):边方向夹角小于此值视为共线,用于冗余顶点清理 + +EnergyPlus 要求几何单位为米且封闭体积,因此 `units: "Meters"` + 合理的 `tolerance` 是导出成功的必要条件。 + +--- + +## 三、Ladybug Tools 现有方案:Dragonfly + +Dragonfly 是 Ladybug Tools 生态中面向社区/城市尺度的独立项目,schema 定义在 `dragonfly-schema`。 + +### 3.1 Dragonfly 层级结构 + +``` +Dragonfly Model +├── buildings[] +│ ├── unique_stories[] +│ │ ├── room_2ds[] ← 2D 楼层板 + 参数化立面 +│ │ └── multiplier ← 标准层复用 +│ ├── room_3ds[] ← 可选的完整 Honeybee Room(3D) +│ └── roof ← 屋顶几何 +├── context_shades[] ← 周边建筑/地形(Face3D / Mesh3D) +├── units / tolerance / angle_tolerance +└── properties ← Energy / Radiance / DOE-2 / Comparison +``` + +### 3.2 Dragonfly 与 Honeybee 的关系 + +``` +Dragonfly (社区/城市尺度) + │ 几何: 2D 楼层板 + 参数化窗户/遮阳/屋顶 + │ ↓ translate_to_honeybee() + ▼ +Honeybee (建筑单体尺度) + │ 几何: 完整 3D Face3D + │ ↓ to_idf() / to_rad() + ▼ +EnergyPlus / Radiance +``` + +关键事实:Dragonfly 不是 HBJSON 的"上层扩展",而是一个**独立的 schema**,通过 `translate_to_honeybee()` 降维生成 HBJSON。 + +### 3.3 Dragonfly 的能力与局限 + +| 尺度 | 能力 | 局限 | +|---|---|---| +| 建筑单体 | Room2D(2D 楼板+参数化立面)→ 可转 Honeybee | 非 3D 精确几何 | +| 建筑群 | Building 列表 + ContextShade | 仅遮阳关系,无交互 | +| 社区 | 多 Building + reference_vector 定位 | 无管网/微气候/能源系统 | + +### 3.4 缺失层(社区 → 城市之间) + +- **区域能源系统**(District Energy)——冷热源站、管网拓扑、换热站 +- **场地要素**——道路、绿地、水体、地形 +- **微气候**——UHI(城市热岛)、风环境耦合 +- **城市尺度**——土地利用分区、交通、人口密度 +- **跨建筑交互**——阴影投射、反射辐射、废热排放 + +--- + +## 四、扩展方案对比 + +### 4.1 方案对比 + +| 方案 | 核心思路 | 优势 | 劣势 | +|---|---|---|---| +| 一:HBJSON 之上增加 Site 层 | 包裹 MultiScaleModel,内嵌 HBJSON | 完全向后兼容,单文件云端模拟 | 文件体积较大 | +| 二:扩展 Dragonfly properties | 在 Dragonfly Model 增加城市扩展 | 与 Ladybug Tools 原生兼容 | Room2D 几何精度不足,HBJSON 反向映射不完美 | +| 三:独立格式 + HBJSON 引用 | CityModel 引用外部 hbjson 文件 | 解耦,可版本控制 | 多文件依赖,不适合云端一键模拟 | + +### 4.2 推荐方案:方案一的增强版 + +在 HBJSON 之上增加 `MultiScaleModel` 容器,保持 HBJSON 结构不变,新增 Site 和 Urban 层级。 + +设计原则: +1. 完全向后兼容——`sites[].buildings[]` 是标准 HBJSON Model,现有工具无需修改 +2. 增量扩展——只增加 Site 和 Urban 两个新层级 +3. 可分级模拟——可只取一个 Site 做社区模拟,也可取全部做城市模拟 + +--- + +## 五、MultiScaleModel Schema 设计 + +### 5.1 顶层结构 + +```json +{ + "type": "MultiScaleModel", + "version": "0.1.0", + "units": "Meters", + "tolerance": 0.01, + "sites": [...], + "properties": { "urban": {...} } +} +``` + +### 5.2 Site 结构(社区/街区尺度) + +``` +Site +├── identifier ← 场地标识 +├── boundary ← 2D 边界 [[x,y], ...] +├── buildings[] ← HBJSON Model(内嵌) +├── context_shades[] ← 周边建筑/地形 +│ +├── terrain ← 地形 +│ ├── type: "Grid" | "TIN" +│ └── data ← 高程网格或三角网 +│ +├── infrastructure ← 基础设施 +│ ├── roads[] ← 道路中心线 + 断面 +│ ├── green_spaces[] ← 绿地(Face3D + 植被类型) +│ └── water_bodies[] ← 水体 +│ +├── district_energy ← 区域能源系统 +│ ├── plants[] ← 源站(CHP、地源热泵、锅炉房) +│ │ ├── type, capacity, cop, fuel_type +│ │ └── location [x, y, z] +│ ├── networks[] ← 管网 +│ │ ├── type: "CHW" | "HW" | "Steam" +│ │ ├── pipes[] ← 管段(起点、终点、管径、保温) +│ │ └── supply_temp, return_temp +│ └── connections[] ← 建筑-管网接入 +│ ├── building_ref, network_ref, flow_rate +│ +└── properties + ├── energy + └── microclimate ← 微气候 + ├── uhi_model ← 热岛强度参数 + └── wind_model ← 风场参数 +``` + +### 5.3 Urban 结构(城市尺度) + +``` +properties.urban +├── climate_zones[] ← 气候分区 +├── land_use[] ← 用地性质 +└── schedule ← 城市级时间表(交通、人口) +``` + +--- + +## 六、关键技术决策 + +| 决策点 | 推荐 | 理由 | +|---|---|---| +| 建筑几何引用 | 内嵌 HBJSON | 保持与 HBJSON 自包含格式的一致性,减少解析复杂度;多文件方案需额外处理文件依赖和版本一致性 | +| 几何精度 | 社区用 Dragonfly Room2D,城市用简模 | 城市尺度不需要 Face 级精度,简化计算 | +| 微气候耦合 | 参数化而非 CFD | CFD 耦合计算量过大,用 UHI 修正系数 | +| 区域能源 | 拓扑网络 + 简化水力模型 | 不需要详细水力计算,关注热平衡 | +| 向后兼容 | 完全保留 HBJSON 结构 | 现有 honeybee 工具链零修改 | + +--- + +## 七、下一步:新增 community/urban 尺度实体 + +当前 `schema-building.json` 已完全对齐 HBJSON(建筑单体几何尺度)。社区和城市尺度的实体定义需要新建独立的 `schema-community.json` / `schema-urban.json`,不应直接混入 schema-building.json,以保持与 HBJSON 的严格兼容。 + +除几何外,各模拟领域均已独立建库,且按尺度拆分: + +- 建筑尺度:`schema-building.json`(几何)/ `schema-energy.json` / `schema-radiance.json` / `schema-cfd.json` +- 社区尺度:`schema-community.json`(几何)/ `schema-community-energy.json` / `schema-community-cfd.json` / `schema-community-microclimate.json` +- 城市尺度:`schema-urban.json`(几何)/ `schema-urban-energy.json` / `schema-urban-cfd.json` + +新增实体规划: + +| 层级 | 文件 | 实体 | +|---|---|---| +| Site 几何 | `schema-community.json` | Site / TerrainGrid / TerrainTIN / Road / GreenSpace / WaterBody | +| 区域能源 | `schema-community-energy.json` | DistrictEnergy / Plant / Network / Pipe / BuildingConnection | +| 社区 CFD | `schema-community-cfd.json` | CommunityCFDSettings / WindProfile / CFDDomain / Mesh / Turbulence | +| 微气候 | `schema-community-microclimate.json` | MicroClimate | +| 城市几何 | `schema-urban.json` | ClimateZone / LandUse | +| 城市能源 | `schema-urban-energy.json` | UrbanEnergyDemand / RenewablePotential / UrbanEnergyBalance | +| 城市 CFD | `schema-urban-cfd.json` | UrbanCFDSettings / WindComfortAssessment | + +MultiScaleModel 作为顶层容器,通过引用方式关联三个尺度: +- `sites[].buildings[]` → 引用 bps/building 的 HBJSON Model +- `sites[].terrain/infrastructure` → 由 bps/community 定义 +- `properties.urban` → 由 bps/urban 定义 diff --git a/pres/assets/base.css b/pres/assets/base.css new file mode 100644 index 0000000..a65418b --- /dev/null +++ b/pres/assets/base.css @@ -0,0 +1,1285 @@ +/** + * base.css — CCTC-CADG 16:9 固定比例基础样式 + * + * 策略: + * 1. body 填充视口,flex 居中,深灰背景 + * 2. .deck 锁定 16:9,通过 width/max-height 自动适配视口 + * 3. 所有内部尺寸(字体/间距/布局)统一用 vmin + */ + +/* ============================================ + 1. 设计令牌(Design Tokens) + ============================================ */ +:root { + --text-pri: #222; + --text-body: #444; + --text-muted: #777; + --text-light: #bbb; + --border: #e8e8e8; + --border-light: #ccc; + --bg-card: #f8f8f8; + --bg-alt: #fafafa; + --bg-white: #fff; + --danger: #b91c1c; + --success: #047857; + --accent: #C00000; + --accent-alt: #555555; + --accent-light: rgba(192, 0, 0, 0.06); + --accent-mid: rgba(192, 0, 0, 0.12); + --gray-seal: rgba(180, 180, 180, 0.18); + --gray-pattern: rgba(180, 180, 180, 0.12); + --red-bar-w: 2.5vmin; + + --hero: 7.5vmin; + --subtitle: 3.5vmin; + --display: 5.5vmin; + --heading: 4vmin; + --body: 3vmin; + --small: 2.8vmin; + --tag: 2vmin; + --mini: 1.6vmin; + --kpi: 6vmin; + --icon-lg: 8vmin; + --thanks: 8vmin; + --seal: 20vmin; + --section-num: 12vmin; + + --space-xs: 0.8vmin; + --space-sm: 1.5vmin; + --space: 2vmin; + --space-lg: 3vmin; + --space-xl: 5vmin; + + --header-h: 14vmin; + --footer-h: 8vmin; + --body-pad-x: 8vmin; + --body-pad-y: 3vmin; + + --hair: 0.1vmin; + --border-w: 0.15vmin; + --med: 0.2vmin; + --strong: 0.6vmin; + + --content-h: 78vmin; + --img-max-showcase: 52vmin; + --img-max-wide: 42vmin; + --img-max-standard: 33vmin; + --img-max-compare: 40vmin; + --img-max-triple: 35vmin; + --img-max-grid: 22vmin; + + --accent-1: var(--accent); + --accent-2: var(--accent-alt); +} + +/* ============================================ + 2. 幻灯片骨架 — 16:9 固定比例容器 + ============================================ */ +/* body 填充视口,居中,深色背景 */ +body, html { + margin: 0; + padding: 0; + width: 100vw; + height: 100vh; + overflow: hidden; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-rendering: optimizeLegibility; +} +body { + background: #1a1a1a; +} + +/* 全屏容器:deck 填满视口,所有内部尺寸用 vmin 同步缩放 */ +.deck.tpl-cctc-cadg { + position: relative; + width: 100vw; + height: 100vh; + overflow: hidden; + font-family: "Microsoft YaHei", "Times New Roman", "PingFang SC", "Helvetica Neue", Arial, sans-serif; + background: var(--bg-white); +} + +.deck.tpl-cctc-cadg .slide { + position: absolute !important; + inset: 0 !important; + padding: 0 !important; + justify-content: flex-start !important; + align-items: stretch !important; + overflow: hidden; + opacity: 0; + pointer-events: none; + transition: opacity 0.5s ease, transform 0.5s ease; + transform: translateX(30px); +} +.deck.tpl-cctc-cadg .slide.is-active { + opacity: 1; + pointer-events: auto; + transform: translateX(0); + z-index: 2; +} +.deck.tpl-cctc-cadg .slide.is-prev { + transform: translateX(-30px); +} + +/* 全屏模式防文字重影 */ +.slide { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; +} +:fullscreen .slide { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + transform: translateZ(0); +} + +/* ============================================ + 3. 页眉页脚 + ============================================ */ +.deck.tpl-cctc-cadg .page-header { + position: absolute; + top: 0; + left: 0; + width: var(--red-bar-w); + height: var(--header-h); + background: var(--accent-1); + z-index: 2; +} +.deck.tpl-cctc-cadg .page-title { + position: absolute; + top: var(--space-xl); + left: var(--body-pad-x); + font-size: var(--heading); + font-weight: bold; + color: var(--accent-1); + letter-spacing: var(--space-xs); + z-index: 3; +} +.deck.tpl-cctc-cadg .page-subtitle { + position: absolute; + top: 10.5vmin; + left: var(--body-pad-x); + font-size: var(--small); + color: var(--text-muted); + z-index: 3; +} +.deck.tpl-cctc-cadg .page-footer { + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: var(--footer-h); + border-top: var(--border-w) solid var(--border); + z-index: 2; +} +.deck.tpl-cctc-cadg .page-footer .footer-logo { + position: absolute; + bottom: var(--space-sm); + left: var(--body-pad-x); + height: var(--space-lg); + opacity: 0.85; +} +.deck.tpl-cctc-cadg .page-footer .footer-url { + position: absolute; + bottom: var(--space); + right: 5vmin; + font-size: var(--mini); + color: var(--text-light); +} +.deck.tpl-cctc-cadg .page-body { + position: absolute; + top: var(--header-h); + bottom: var(--footer-h); + left: 0; + right: 0; + padding: var(--space-lg) var(--body-pad-x); + z-index: 2; + overflow: hidden; + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: stretch; +} +.deck.tpl-cctc-cadg .page-body ul { + padding-left: var(--space-lg); + font-size: var(--body); + line-height: 1.6; +} +.deck.tpl-cctc-cadg .page-body li { + margin-bottom: var(--space-sm); + font-size: var(--body); + line-height: 1.5; +} +.deck.tpl-cctc-cadg .page-body li::marker { + color: var(--accent-1); +} +.deck.tpl-cctc-cadg .page-body h3 { + font-size: var(--heading); + font-weight: bold; + color: var(--text-pri); + margin-bottom: var(--space); +} +.deck.tpl-cctc-cadg .page-body p { + font-size: var(--body); + color: var(--text-body); + line-height: 1.7; +} +.deck.tpl-cctc-cadg .page-body table { + width: 100%; + border-collapse: collapse; + font-size: var(--small); +} +.deck.tpl-cctc-cadg .page-body th { + background: var(--accent-1); + color: var(--bg-white); + padding: var(--space-sm) 2vmin; + text-align: left; + font-weight: bold; +} +.deck.tpl-cctc-cadg .page-body td { + padding: var(--space-sm) 2vmin; + border-bottom: var(--border-w) solid var(--border); +} +.deck.tpl-cctc-cadg .page-body tr:nth-child(even) { + background: var(--bg-alt); +} + +/* ============================================ + 4. 封面 + ============================================ */ +.deck.tpl-cctc-cadg .slide-cover { + background: var(--bg-white); +} +.deck.tpl-cctc-cadg .slide-cover::before { + content: ""; + position: absolute; + left: 0; + top: 0; + bottom: 0; + width: var(--red-bar-w); + background: var(--accent-1); + z-index: 1; +} +.deck.tpl-cctc-cadg .slide-cover .dot-grid { + position: absolute; + right: 0; + bottom: 0; + width: 50%; + height: 55%; + background-image: radial-gradient(circle, var(--border-light) 1.2px, transparent 1.2px); + background-size: var(--space) var(--space); + z-index: 0; + -webkit-mask-image: linear-gradient(to top left, rgba(0,0,0,0.7) 20%, transparent 70%); + mask-image: linear-gradient(to top left, rgba(0,0,0,0.7) 20%, transparent 70%); +} +.deck.tpl-cctc-cadg .slide-cover .cover-content { + position: absolute; + left: calc(var(--red-bar-w) + 4.5vmin); + top: 22%; + z-index: 2; +} +.deck.tpl-cctc-cadg .slide-cover .cover-org { + font-size: var(--body); + color: var(--text-light); + margin-bottom: var(--space-lg); + letter-spacing: var(--space-xs); +} +.deck.tpl-cctc-cadg .slide-cover .cover-title { + font-size: var(--hero); + font-weight: bold; + color: var(--text-pri); + margin-bottom: var(--space-lg); + line-height: 1.25; +} +.deck.tpl-cctc-cadg .slide-cover .cover-subtitle { + font-size: var(--subtitle); + color: var(--accent-1); + font-weight: bold; + margin-bottom: 15vmin; + line-height: 1.4; +} +.deck.tpl-cctc-cadg .slide-cover .cover-presenter { + font-size: var(--body); + color: var(--text-muted); +} +.deck.tpl-cctc-cadg .slide-cover .cover-presenter p { + margin: var(--space-sm) 0; +} +.deck.tpl-cctc-cadg .slide-cover .cover-logo { + position: absolute; + top: var(--space-xl); + right: 5vmin; + z-index: 3; + height: var(--space-xl); +} +.deck.tpl-cctc-cadg .slide-cover .cover-url { + position: absolute; + bottom: var(--space-lg); + right: 5vmin; + font-size: var(--mini); + color: var(--text-light); + z-index: 2; +} + +/* ============================================ + 5. 目录页 + ============================================ */ +.deck.tpl-cctc-cadg .slide-toc { + background: var(--bg-white); + flex-direction: column; + align-items: flex-start; + justify-content: flex-start; +} +.deck.tpl-cctc-cadg .slide-toc .seal-left, +.deck.tpl-cctc-cadg .slide-toc .seal-right { + position: absolute; + top: 50%; + transform: translateY(-50%); + font-family: "KaiTi", "STKaiti", serif; + font-size: var(--seal); + color: var(--gray-seal); + writing-mode: vertical-rl; + letter-spacing: var(--space-sm); + z-index: 0; + user-select: none; +} +.deck.tpl-cctc-cadg .slide-toc .seal-left { left: 5%; } +.deck.tpl-cctc-cadg .slide-toc .seal-right { right: 5%; } +.deck.tpl-cctc-cadg .slide-toc .toc-title { + font-size: var(--display); + font-weight: bold; + color: var(--text-body); + margin-top: 13vmin; + margin-bottom: var(--space-xl); + z-index: 2; + padding-left: var(--space-xl); + letter-spacing: var(--space-xs); +} +.deck.tpl-cctc-cadg .slide-toc .toc-list { + list-style: none; + padding: 0 var(--space-xl); + z-index: 2; + width: 50%; +} +.deck.tpl-cctc-cadg .slide-toc .toc-list li { + font-size: var(--heading); + font-weight: bold; + color: var(--text-pri); + padding: var(--space) 0; + border-bottom: var(--border-w) solid var(--border); +} +.deck.tpl-cctc-cadg .slide-toc .toc-list li .toc-num { + color: var(--accent-1); + margin-right: var(--space-sm); +} +.deck.tpl-cctc-cadg .slide-toc .toc-list li .toc-sub { + font-size: var(--tag); + font-weight: normal; + color: var(--text-light); + margin-left: var(--space-sm); +} +.deck.tpl-cctc-cadg .slide-toc .toc-logo { + position: absolute; + bottom: var(--space-xl); + left: 50%; + transform: translateX(-50%); + height: var(--space-lg); + z-index: 2; +} + +/* ============================================ + 6. 节标题页 + ============================================ */ +.deck.tpl-cctc-cadg .slide-section { + background: var(--bg-white); + align-items: flex-start; + justify-content: flex-start; +} +.deck.tpl-cctc-cadg .slide-section::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: var(--red-bar-w); + height: var(--header-h); + background: var(--accent-1); + z-index: 2; +} +.deck.tpl-cctc-cadg .slide-section .section-body { + position: absolute; + top: var(--header-h); + bottom: var(--footer-h); + left: 19vmin; + right: 0; + padding: var(--space-xl) var(--body-pad-x); + z-index: 2; +} +.deck.tpl-cctc-cadg .slide-section .section-num { + font-size: var(--section-num); + font-weight: bold; + color: var(--accent-1); + opacity: 0.12; + position: absolute; + left: -10vmin; + top: 0; + z-index: 1; +} +.deck.tpl-cctc-cadg .slide-section .section-main-title { + font-size: var(--display); + font-weight: bold; + color: var(--accent-1); + margin-bottom: var(--space); + z-index: 2; + position: relative; +} +.deck.tpl-cctc-cadg .slide-section .section-main-title::after { + content: ""; + display: block; + width: var(--space-xl); + height: var(--med); + background: var(--accent-2); + margin-top: var(--space); +} +.deck.tpl-cctc-cadg .slide-section .section-subtitle { + font-size: var(--body); + color: var(--text-muted); + z-index: 2; + position: relative; + margin-top: var(--space-sm); +} +.deck.tpl-cctc-cadg .slide-section .page-footer { + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: var(--footer-h); + border-top: var(--border-w) solid var(--border); + z-index: 2; +} +.deck.tpl-cctc-cadg .slide-section .page-footer .footer-url { + position: absolute; + bottom: var(--space); + right: 5vmin; + font-size: var(--mini); + color: var(--text-light); +} + +/* ============================================ + 7. 感谢页 + ============================================ */ +.deck.tpl-cctc-cadg .slide-thanks { + background: var(--bg-white); + flex-direction: column; +} +.deck.tpl-cctc-cadg .slide-thanks::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: var(--red-bar-w); + height: auto; + min-height: 28vmin; + background: var(--accent-1); + z-index: 1; +} +.deck.tpl-cctc-cadg .slide-thanks .thanks-logo { + position: absolute; + top: var(--space-xl); + right: 5vmin; + z-index: 3; + height: var(--space-xl); +} +.deck.tpl-cctc-cadg .slide-thanks .thanks-pattern { + position: absolute; + bottom: var(--header-h); + left: calc(var(--red-bar-w) + 4vmin); + right: 5vmin; + height: 13vmin; + background: + repeating-linear-gradient(45deg, transparent, transparent 3.5vmin, var(--gray-pattern) 3.5vmin, var(--gray-pattern) calc(3.5vmin + 1px)), + repeating-linear-gradient(-45deg, transparent, transparent 3.5vmin, var(--gray-pattern) 3.5vmin, var(--gray-pattern) calc(3.5vmin + 1px)); + z-index: 1; +} +.deck.tpl-cctc-cadg .slide-thanks .thanks-text { + font-size: var(--thanks); + font-weight: bold; + color: var(--text-muted); + z-index: 2; + position: absolute; + left: 0; + right: 0; + text-align: center; + bottom: 20vmin; +} +.deck.tpl-cctc-cadg .slide-thanks .thanks-url { + position: absolute; + bottom: var(--space-lg); + right: 5vmin; + font-size: var(--mini); + color: var(--text-light); + z-index: 2; +} + +/* ============================================ + 8. 运行时 UI 样式 + ============================================ */ +.deck.tpl-cctc-cadg .progress-bar { + background: var(--accent-1); +} +.deck.tpl-cctc-cadg .deck-footer { display: none; } +.notes-overlay { display: none; } +.notes-overlay.open { display: block; } +.overview { display: none; } +.overview.open { display: block; } + +/* ============================================ + 9. 布局组件 + ============================================ */ +.deck.tpl-cctc-cadg .two-col { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--space-lg); + min-height: 28vmin; + flex: 1; +} +.deck.tpl-cctc-cadg .three-col { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: var(--space); + min-height: 18vmin; + flex: 1; +} +.deck.tpl-cctc-cadg .four-col { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: var(--space); + flex: 1; +} +.deck.tpl-cctc-cadg .step-flow { + display: flex; + align-items: center; + gap: var(--space-sm); + margin: var(--space) 0; + flex: 1; +} +.deck.tpl-cctc-cadg .step-item { + background: var(--bg-card); + padding: var(--space) 2vmin; + border-radius: 0.8vmin; + text-align: center; + border: var(--border-w) solid var(--border); + flex: 1; +} +.deck.tpl-cctc-cadg .step-item .step-num { + font-size: 4vmin; + font-weight: bold; + color: var(--accent-1); + display: block; + margin-bottom: 1vmin; +} +.deck.tpl-cctc-cadg .step-item .step-label { + font-size: var(--body); + font-weight: bold; + color: var(--text-pri); + display: block; +} +.deck.tpl-cctc-cadg .step-item .step-desc { + font-size: var(--tag); + color: var(--text-muted); + margin-top: var(--space-xs); + display: block; +} +.deck.tpl-cctc-cadg .step-arrow { + font-size: var(--body); + color: var(--border-light); +} +.deck.tpl-cctc-cadg .center-layout { + text-align: center; + max-width: 70%; + margin: 0 auto; +} +.deck.tpl-cctc-cadg .center-layout .cl-icon { + font-size: 8vmin; + margin-bottom: var(--space); +} +.deck.tpl-cctc-cadg .center-layout .cl-title { + font-size: 4vmin; + font-weight: bold; + color: var(--text-pri); + margin-bottom: var(--space-sm); +} +.deck.tpl-cctc-cadg .center-layout .cl-desc { + font-size: var(--body); + color: #555; + line-height: 1.6; +} + +/* ============================================ + 10. 图文布局 + ============================================ */ +.deck.tpl-cctc-cadg .illustration-left, +.deck.tpl-cctc-cadg .illustration-right { + display: flex; + gap: var(--space-lg); + align-items: center; +} +.deck.tpl-cctc-cadg .illustration-left .image-container, +.deck.tpl-cctc-cadg .illustration-right .image-container { + flex: 0 0 45%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 0.4vmin; +} +.deck.tpl-cctc-cadg .illustration-left .image-container img, +.deck.tpl-cctc-cadg .illustration-right .image-container img { + max-height: var(--img-max-standard); + width: auto; + object-fit: contain; +} +.deck.tpl-cctc-cadg .illustration-left .text-container, +.deck.tpl-cctc-cadg .illustration-right .text-container { + flex: 1; +} + +.deck.tpl-cctc-cadg .illustration-left.wide, +.deck.tpl-cctc-cadg .illustration-right.wide { + display: flex; + gap: var(--space-lg); + align-items: center; +} +.deck.tpl-cctc-cadg .illustration-left.wide .image-container, +.deck.tpl-cctc-cadg .illustration-right.wide .image-container { + flex: 0 0 55%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 0.4vmin; +} +.deck.tpl-cctc-cadg .illustration-left.wide .image-container img, +.deck.tpl-cctc-cadg .illustration-right.wide .image-container img { + max-height: var(--img-max-wide); + width: 100%; + object-fit: contain; +} +.deck.tpl-cctc-cadg .illustration-left.wide .text-container, +.deck.tpl-cctc-cadg .illustration-right.wide .text-container { + flex: 1; +} + +.deck.tpl-cctc-cadg .showcase-image { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + flex: 1; + gap: var(--space); +} +.deck.tpl-cctc-cadg .showcase-image .image-container { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} +.deck.tpl-cctc-cadg .showcase-image .image-container img { + max-height: var(--img-max-showcase); + width: 100%; + object-fit: contain; +} +.deck.tpl-cctc-cadg .showcase-image .image-caption { + font-size: var(--tag); + color: var(--text-muted); + text-align: center; +} + +.deck.tpl-cctc-cadg .dual-image-compare { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--space-lg); + flex: 1; +} +.deck.tpl-cctc-cadg .dual-image-compare .compare-panel { + display: flex; + flex-direction: column; + background: var(--bg-card); + border-radius: 0.8vmin; + border: 1px solid var(--border-light); + overflow: hidden; +} +.deck.tpl-cctc-cadg .dual-image-compare .compare-label { + font-size: var(--tag); + font-weight: bold; + color: var(--accent-1); + padding: 1vmin 1.5vmin; + background: var(--accent-light); + text-align: center; +} +.deck.tpl-cctc-cadg .dual-image-compare .image-container { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 1vmin; +} +.deck.tpl-cctc-cadg .dual-image-compare .image-container img { + max-height: var(--img-max-compare); + width: 100%; + object-fit: contain; +} + +/* ============================================ + 多图网格布局 + ============================================ */ +.deck.tpl-cctc-cadg .image-grid-1x3 { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 1.5vmin; + flex: 1; +} +.deck.tpl-cctc-cadg .image-grid-1x4 { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 0.8vmin; + flex: 1; +} +.deck.tpl-cctc-cadg .image-grid-1x5 { + display: grid; + grid-template-columns: repeat(5, 1fr); + gap: 0.6vmin; + flex: 1; +} +.deck.tpl-cctc-cadg .image-grid-1x3 .grid-img-item, +.deck.tpl-cctc-cadg .image-grid-1x4 .grid-img-item, +.deck.tpl-cctc-cadg .image-grid-1x5 .grid-img-item { + display: flex; + flex-direction: column; + align-items: center; + overflow: hidden; +} +.deck.tpl-cctc-cadg .image-grid-1x3 .grid-img-item img, +.deck.tpl-cctc-cadg .image-grid-1x4 .grid-img-item img, +.deck.tpl-cctc-cadg .image-grid-1x5 .grid-img-item img { + max-height: var(--img-max-grid); + width: 100%; + object-fit: contain; +} +.deck.tpl-cctc-cadg .image-grid-1x3 .grid-img-caption, +.deck.tpl-cctc-cadg .image-grid-1x4 .grid-img-caption, +.deck.tpl-cctc-cadg .image-grid-1x5 .grid-img-caption { + font-size: 1.4vmin; + color: var(--text-muted); + text-align: center; + margin-top: 0.2vmin; + line-height: 1.2; +} + +.deck.tpl-cctc-cadg .hybrid-text-grid { + display: flex; + gap: 1.5vmin; + flex: 1; +} +.deck.tpl-cctc-cadg .hybrid-text-grid .hybrid-text { + flex: 0 0 38%; + display: flex; + flex-direction: column; + gap: 0.8vmin; +} +.deck.tpl-cctc-cadg .hybrid-text-grid .hybrid-text p, +.deck.tpl-cctc-cadg .hybrid-text-grid .hybrid-text li { + font-size: 2.4vmin; + line-height: 1.4; +} +.deck.tpl-cctc-cadg .hybrid-text-grid .hybrid-grid { + flex: 1; + display: grid; + gap: 0.8vmin; +} +.deck.tpl-cctc-cadg .hybrid-text-grid .hybrid-grid.grid-2col { + grid-template-columns: repeat(2, 1fr); +} +.deck.tpl-cctc-cadg .hybrid-text-grid .hybrid-grid.grid-3col { + grid-template-columns: repeat(3, 1fr); +} +.deck.tpl-cctc-cadg .hybrid-text-grid .hybrid-grid .grid-img-item { + display: flex; + flex-direction: column; + align-items: center; + overflow: hidden; +} +.deck.tpl-cctc-cadg .hybrid-text-grid .hybrid-grid .grid-img-item img { + max-height: 20vmin; + width: 100%; + object-fit: contain; +} +.deck.tpl-cctc-cadg .hybrid-text-grid .hybrid-grid .grid-img-item .grid-img-caption { + font-size: 1.3vmin; + color: var(--text-muted); + text-align: center; + margin-top: 0.2vmin; + line-height: 1.2; +} + +/* 图注 */ +.image-caption { + margin-top: 0.4vmin; + font-size: 1.6vmin; + color: #555; + text-align: center; + line-height: 1.35; + font-style: normal; +} +.showcase-image .image-caption { + margin-top: 0.6vmin; +} + +/* ============================================ + 11. 卡片组件 + ============================================ */ +.deck.tpl-cctc-cadg .kpi-card { + background: var(--bg-card); + padding: var(--space) 2vmin; + border-radius: 0.8vmin; + text-align: center; + border: var(--border-w) solid var(--border); +} +.deck.tpl-cctc-cadg .kpi-card .kpi-value { + font-size: var(--kpi); + font-weight: bold; + color: var(--accent-1); + display: block; + margin-bottom: 1vmin; +} +.deck.tpl-cctc-cadg .kpi-card .kpi-label { + font-size: var(--body); + font-weight: bold; + color: var(--text-pri); + display: block; +} +.deck.tpl-cctc-cadg .kpi-card .kpi-desc { + font-size: var(--tag); + color: var(--text-muted); + margin-top: var(--space-xs); + display: block; +} + +.deck.tpl-cctc-cadg .content-card { + background: var(--bg-card); + padding: var(--space) 2vmin; + border-radius: 0.8vmin; + margin-bottom: var(--space); + border: var(--border-w) solid var(--border); + font-size: var(--small); + color: var(--text-body); + line-height: 1.6; +} +.deck.tpl-cctc-cadg .content-card .card-title { + font-size: var(--heading); + font-weight: bold; + color: var(--accent-1); + margin-bottom: var(--space-sm); +} +.deck.tpl-cctc-cadg .content-card .card-body { + font-size: var(--body); + line-height: 1.6; +} + +.deck.tpl-cctc-cadg .comp-box { + background: var(--bg-card); + padding: var(--space) 2vmin; + border-radius: 0.8vmin; + border: var(--border-w) solid var(--border); + font-size: var(--small); + color: var(--text-body); + line-height: 1.6; + align-self: start; +} +.deck.tpl-cctc-cadg .comp-box .comp-title { + font-size: var(--heading); + font-weight: bold; + color: var(--accent-1); + margin-bottom: var(--space-sm); + text-align: center; +} +.deck.tpl-cctc-cadg .comp-box .comp-desc { + font-size: var(--body); + line-height: 1.6; +} +.deck.tpl-cctc-cadg .comp-box .comp-features { + margin-top: var(--space-sm); + padding-left: 2vmin; +} +.deck.tpl-cctc-cadg .comp-box .comp-features li { + font-size: var(--body); + margin-bottom: var(--space-xs); + line-height: 1.5; +} +.deck.tpl-cctc-cadg .comp-box h3 { + font-size: var(--heading); + margin-bottom: var(--space-sm); +} +.deck.tpl-cctc-cadg .comp-box ul { + font-size: var(--body); + padding-left: var(--space-xl); +} +.deck.tpl-cctc-cadg .comp-box.bad { border-color: var(--danger); } +.deck.tpl-cctc-cadg .comp-box.good { border-color: var(--success); } +.deck.tpl-cctc-cadg .comp-box.neutral { border-color: var(--text-muted); background: var(--bg-alt); } + +.deck.tpl-cctc-cadg .quote-box { + background: var(--accent-light); + border-left: var(--med) solid var(--accent-1); + padding: var(--space) 2vmin; + margin: var(--space) 0; + border-radius: 0 0.8vmin 0.8vmin 0; + font-size: var(--small); + color: var(--text-body); + line-height: 1.6; +} +.deck.tpl-cctc-cadg .quote-box .quote-text { + font-size: var(--body); + font-style: italic; + line-height: 1.6; +} +.deck.tpl-cctc-cadg .quote-box .quote-source { + font-size: var(--tag); + color: var(--text-muted); + margin-top: var(--space-xs); +} + +.deck.tpl-cctc-cadg .conclusion-box { + background: var(--accent-light); + border: var(--border-w) solid var(--accent-1); + padding: var(--space) 2vmin; + border-radius: 0.8vmin; + margin: var(--space) 0; +} +.deck.tpl-cctc-cadg .conclusion-box .conclusion-title { + font-size: var(--heading); + font-weight: bold; + color: var(--accent-1); + margin-bottom: var(--space-sm); +} +.deck.tpl-cctc-cadg .conclusion-box .conclusion-body { + font-size: var(--body); + line-height: 1.6; +} + +.deck.tpl-cctc-cadg .ref-block { + background: var(--bg-card); + padding: var(--space) 2vmin; + border-radius: 0.8vmin; + border: var(--border-w) solid var(--border); + margin: var(--space) 0; +} +.deck.tpl-cctc-cadg .ref-block .ref-title { + font-size: var(--heading); + font-weight: bold; + color: var(--accent-1); + margin-bottom: var(--space-sm); +} +.deck.tpl-cctc-cadg .ref-block .ref-body { + font-size: var(--body); + line-height: 1.6; +} + +.deck.tpl-cctc-cadg .data-panel { + background: var(--bg-card); + padding: var(--space) 2vmin; + border-radius: 0.8vmin; + border: var(--border-w) solid var(--border); +} +.deck.tpl-cctc-cadg .data-panel .panel-title { + font-size: var(--heading); + font-weight: bold; + color: var(--accent-1); + margin-bottom: var(--space-sm); + text-align: center; +} +.deck.tpl-cctc-cadg .data-panel .panel-body { + font-size: var(--body); + line-height: 1.6; +} + +.deck.tpl-cctc-cadg .param-cards { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(25vmin, 1fr)); + gap: var(--space); + margin: var(--space) 0; +} +.deck.tpl-cctc-cadg .param-card { + background: var(--bg-card); + padding: var(--space) 2vmin; + border-radius: 0.8vmin; + border: var(--border-w) solid var(--border); + text-align: center; +} +.deck.tpl-cctc-cadg .param-card .param-name { + font-size: var(--body); + font-weight: bold; + color: var(--text-pri); + margin-bottom: var(--space-xs); +} +.deck.tpl-cctc-cadg .param-card .param-value { + font-size: var(--heading); + font-weight: bold; + color: var(--accent-1); +} +.deck.tpl-cctc-cadg .param-card .param-unit { + font-size: var(--tag); + color: var(--text-muted); + margin-left: var(--space-xs); +} + +/* ============================================ + 12. 图表组件 + ============================================ */ +.deck.tpl-cctc-cadg .system-diagram { + display: flex; + flex-direction: column; + gap: var(--space-sm); + min-height: 28vmin; + flex: 1; +} +.deck.tpl-cctc-cadg .diagram-layer { + padding: var(--space); + border-radius: 0.8vmin; + text-align: center; + flex: 1; + display: flex; + align-items: center; + justify-content: center; + font-size: var(--tag); + line-height: 1.6; + box-sizing: border-box; +} +.deck.tpl-cctc-cadg .diagram-layer.input { + background: var(--accent-light); + border-left: var(--med) solid var(--accent-1); + font-size: var(--body); +} +.deck.tpl-cctc-cadg .diagram-layer.core { + background: var(--accent-mid); + border-left: var(--med) solid var(--accent-1); + font-weight: bold; + font-size: var(--body); +} +.deck.tpl-cctc-cadg .diagram-layer.output { + background: var(--bg-card); + border-left: var(--med) solid var(--text-light); + font-size: var(--body); +} + +.deck.tpl-cctc-cadg .research-framework { + display: flex; + gap: var(--space-sm); + align-items: stretch; +} +.deck.tpl-cctc-cadg .research-framework .rf-column { + flex: 1; + background: var(--bg-card); + border-radius: 0.8vmin; + padding: var(--space); + display: flex; + flex-direction: column; +} +.deck.tpl-cctc-cadg .research-framework .rf-header { + font-size: var(--body); + font-weight: bold; + color: var(--accent-1); + margin-bottom: var(--space-sm); + padding-bottom: var(--space-sm); + border-bottom: var(--border-w) solid var(--border); +} +.deck.tpl-cctc-cadg .research-framework .rf-body { + flex: 1; + font-size: var(--body); + color: var(--text-body); + line-height: 1.6; +} +.deck.tpl-cctc-cadg .research-framework .rf-arrow { + flex: 0 0 var(--space); + display: flex; + align-items: center; + justify-content: center; + font-size: var(--body); + color: var(--border-light); +} + +.deck.tpl-cctc-cadg .equation-block { + display: flex; + align-items: center; + justify-content: center; + gap: var(--space); + padding: var(--space) 0; +} +.deck.tpl-cctc-cadg .equation-block .equation-text { + font-size: var(--heading); + font-family: "Times New Roman", "STSong", serif; +} +.deck.tpl-cctc-cadg .equation-block .equation-num { + font-size: var(--small); + color: var(--text-muted); +} +.deck.tpl-cctc-cadg .equation-notes { + font-size: var(--tag); + color: var(--text-muted); + margin-top: var(--space-sm); + padding-left: var(--space-xl); +} + +/* ============================================ + 13. 工具类 + ============================================ */ +.deck.tpl-cctc-cadg .sci-table { + width: 100%; + border-collapse: collapse; + font-size: var(--body); +} +.deck.tpl-cctc-cadg .sci-table thead tr { + border-top: var(--med) solid var(--text-pri); + border-bottom: var(--border-w) solid var(--text-pri); +} +.deck.tpl-cctc-cadg .sci-table th { + background: none; + color: var(--text-pri); + padding: var(--space-sm) 2vmin; + text-align: left; + font-weight: bold; +} +.deck.tpl-cctc-cadg .sci-table td { + padding: var(--space-sm) 2vmin; + border-bottom: var(--hair) solid var(--border); +} +.deck.tpl-cctc-cadg .sci-table tbody tr:last-child { + border-bottom: var(--med) solid var(--text-pri); +} + +.deck.tpl-cctc-cadg .text-small { font-size: var(--small); } +.deck.tpl-cctc-cadg .text-body { font-size: var(--body); } +.deck.tpl-cctc-cadg .text-heading { font-size: var(--heading); } +.deck.tpl-cctc-cadg .text-display { font-size: var(--display); } +.deck.tpl-cctc-cadg .text-bold { font-weight: bold; } +.deck.tpl-cctc-cadg .icon-lg { font-size: var(--display); margin-bottom: 1.5vmin; } + +.deck.tpl-cctc-cadg .text-accent { color: var(--accent-1); } +.deck.tpl-cctc-cadg .text-muted { color: var(--text-muted); } +.deck.tpl-cctc-cadg .text-danger { color: var(--danger); } +.deck.tpl-cctc-cadg .text-success { color: var(--success); } +.deck.tpl-cctc-cadg .text-center { text-align: center; } +.deck.tpl-cctc-cadg .text-left { text-align: left; } +.deck.tpl-cctc-cadg .text-right { text-align: right; } +.deck.tpl-cctc-cadg .bg-accent-light { background: var(--accent-light); } + +.deck.tpl-cctc-cadg .flex { display: flex; } +.deck.tpl-cctc-cadg .flex-1 { flex: 1; } +.deck.tpl-cctc-cadg .flex-1-2 { flex: 1.2; } +.deck.tpl-cctc-cadg .flex-col { flex-direction: column; } +.deck.tpl-cctc-cadg .items-center { align-items: center; } +.deck.tpl-cctc-cadg .items-stretch { align-items: stretch; } +.deck.tpl-cctc-cadg .justify-center { justify-content: center; } +.deck.tpl-cctc-cadg .justify-start { justify-content: flex-start; } +.deck.tpl-cctc-cadg .justify-end { justify-content: flex-end; } + +.deck.tpl-cctc-cadg .mb-3 { margin-bottom: 3vmin; } +.deck.tpl-cctc-cadg .mb-2 { margin-bottom: 2vmin; } +.deck.tpl-cctc-cadg .mb-1-5 { margin-bottom: 1.5vmin; } +.deck.tpl-cctc-cadg .mb-1-2 { margin-bottom: 1.2vmin; } +.deck.tpl-cctc-cadg .mb-1 { margin-bottom: 1vmin; } +.deck.tpl-cctc-cadg .mb-0-5 { margin-bottom: 0.5vmin; } +.deck.tpl-cctc-cadg .mb-0-4 { margin-bottom: 0.4vmin; } +.deck.tpl-cctc-cadg .mt-3 { margin-top: 3vmin; } +.deck.tpl-cctc-cadg .mt-2 { margin-top: 2vmin; } +.deck.tpl-cctc-cadg .mt-1-5 { margin-top: 1.5vmin; } +.deck.tpl-cctc-cadg .mt-1 { margin-top: 1vmin; } +.deck.tpl-cctc-cadg .m-0 { margin: 0; } +.deck.tpl-cctc-cadg .p-2 { padding: 2vmin; } +.deck.tpl-cctc-cadg .pl-1-5 { padding-left: 1.5vmin; } +.deck.tpl-cctc-cadg .gap-3 { gap: 3vmin; } +.deck.tpl-cctc-cadg .gap-1-5 { gap: 1.5vmin; } +.deck.tpl-cctc-cadg .gap-1 { gap: 1vmin; } +.deck.tpl-cctc-cadg .gap-0-8 { gap: 0.8vmin; } + +.deck.tpl-cctc-cadg .border-accent { border: var(--med) solid var(--accent-1); } +.deck.tpl-cctc-cadg .border-top-accent { border-top: 0.4vmin solid var(--accent-1); } +.deck.tpl-cctc-cadg .border-top-success { border-top: 0.4vmin solid var(--success); } +.deck.tpl-cctc-cadg .rounded-sm { border-radius: 0.8vmin; } + +.deck.tpl-cctc-cadg .overflow-hidden { overflow: hidden; } +.deck.tpl-cctc-cadg .w-80 { width: 80%; } +.deck.tpl-cctc-cadg .w-full { width: 100%; } +.deck.tpl-cctc-cadg .max-h-32 { max-height: 32vmin; } +.deck.tpl-cctc-cadg .leading-4 { line-height: 1.4; } +.deck.tpl-cctc-cadg .leading-6 { line-height: 1.6; } +.deck.tpl-cctc-cadg .leading-8 { line-height: 1.8; } + +/* 紧凑变体 */ +.deck.tpl-cctc-cadg .text-compact { font-size: 2.4vmin !important; line-height: 1.4 !important; } +.deck.tpl-cctc-cadg .text-compact-sm { font-size: 2vmin !important; line-height: 1.3 !important; } +.deck.tpl-cctc-cadg .heading-compact { font-size: 3.2vmin !important; line-height: 1.3 !important; } +.deck.tpl-cctc-cadg .comp-box.compact { padding: 1vmin 1.5vmin !important; } +.deck.tpl-cctc-cadg .comp-box.compact .comp-title { font-size: 2.6vmin !important; margin-bottom: 0.3vmin !important; } +.deck.tpl-cctc-cadg .comp-box.compact .comp-desc, +.deck.tpl-cctc-cadg .comp-box.compact ul, +.deck.tpl-cctc-cadg .comp-box.compact li { font-size: 2.2vmin !important; line-height: 1.35 !important; } +.deck.tpl-cctc-cadg .comp-box.compact ul { padding-left: 1.5vmin !important; } +.deck.tpl-cctc-cadg .comp-box.compact li { margin-bottom: 0.2vmin !important; } +.deck.tpl-cctc-cadg .gap-compact { gap: 0.8vmin !important; } +.deck.tpl-cctc-cadg .mb-compact { margin-bottom: 0.8vmin !important; } + +/* 溢出检测 */ +.deck.tpl-cctc-cadg .page-body.overflow-warning { + outline: 1px dashed var(--danger); +} + +/* ===== 打印 / 导出 PDF ===== */ +/* 使用 Chrome headless: + /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \ + --headless=new --disable-gpu \ + --print-to-pdf="/path/to/output.pdf" \ + "file:///path/to/presentation.html" +*/ +@page { size: 10in 5.625in; margin: 0; } +@media print { + html, body { + width: 10in; height: auto; margin: 0; padding: 0; + -webkit-print-color-adjust: exact; print-color-adjust: exact; + background: white; + } + .deck.tpl-cctc-cadg { + position: static; width: 10in; height: auto; overflow: visible; + background: white; + } + .deck.tpl-cctc-cadg .slide { + position: relative !important; + width: 10in; height: auto; + max-height: 5.625in; aspect-ratio: 16 / 9; + opacity: 1 !important; transform: none !important; + display: flex !important; flex-direction: column; + page-break-after: always; page-break-inside: avoid; + margin: 0; padding: 0; overflow: hidden; + box-sizing: border-box; + -webkit-print-color-adjust: exact; print-color-adjust: exact; + background: var(--bg-white); + z-index: auto; pointer-events: auto !important; + } + .deck.tpl-cctc-cadg .slide.is-active, + .deck.tpl-cctc-cadg .slide.is-prev { + transform: none; opacity: 1; + } + /* Override absolute positioning on slide sub-types */ + .deck.tpl-cctc-cadg .slide-cover, + .deck.tpl-cctc-cadg .slide-toc, + .deck.tpl-cctc-cadg .slide-section, + .deck.tpl-cctc-cadg .slide-content, + .deck.tpl-cctc-cadg .slide-thanks { + position: relative !important; + } + /* Hide runtime chrome */ + .progress-bar, .notes-overlay, .overview, aside.notes { display: none !important; } + /* Kill animations */ + * { animation: none !important; transition: none !important; } +} diff --git a/pres/assets/images/cctc-cadg/banner.png b/pres/assets/images/cctc-cadg/banner.png new file mode 100644 index 0000000..e35a015 Binary files /dev/null and b/pres/assets/images/cctc-cadg/banner.png differ diff --git a/pres/assets/images/cctc-cadg/contents-bg.jpg b/pres/assets/images/cctc-cadg/contents-bg.jpg new file mode 100644 index 0000000..2125e19 Binary files /dev/null and b/pres/assets/images/cctc-cadg/contents-bg.jpg differ diff --git a/pres/assets/images/cctc-cadg/cover-bg.jpg b/pres/assets/images/cctc-cadg/cover-bg.jpg new file mode 100644 index 0000000..06c73c9 Binary files /dev/null and b/pres/assets/images/cctc-cadg/cover-bg.jpg differ diff --git a/pres/assets/images/cctc-cadg/header-bg.jpg b/pres/assets/images/cctc-cadg/header-bg.jpg new file mode 100644 index 0000000..a9d0c36 Binary files /dev/null and b/pres/assets/images/cctc-cadg/header-bg.jpg differ diff --git a/pres/assets/images/cctc-cadg/header.jpg b/pres/assets/images/cctc-cadg/header.jpg new file mode 100644 index 0000000..a9d0c36 Binary files /dev/null and b/pres/assets/images/cctc-cadg/header.jpg differ diff --git a/pres/assets/images/cctc-cadg/logo.png b/pres/assets/images/cctc-cadg/logo.png new file mode 100644 index 0000000..e8f7cbe Binary files /dev/null and b/pres/assets/images/cctc-cadg/logo.png differ diff --git a/pres/assets/runtime.js b/pres/assets/runtime.js new file mode 100644 index 0000000..9d9ee95 --- /dev/null +++ b/pres/assets/runtime.js @@ -0,0 +1,1003 @@ +/* html-ppt :: runtime.js + * Keyboard-driven deck runtime. Zero dependencies. + * + * Features: + * ← → / space / PgUp PgDn / Home End navigation + * F fullscreen + * S presenter mode (opens a NEW WINDOW with current/next slide preview + notes + timer) + * The original window stays as audience view, synced via BroadcastChannel. + * Slide previews use CSS transform:scale() at design resolution for pixel-perfect layout. + * N quick notes overlay (bottom drawer) + * O slide overview grid + * T cycle themes (reads data-themes on or ) + * A cycle demo animation on current slide + * URL hash #/N deep-link to slide N (1-based) + * Progress bar auto-managed + */ +(function () { + 'use strict'; + + const ANIMS = ['fade-up','fade-down','fade-left','fade-right','rise-in','drop-in', + 'zoom-pop','blur-in','glitch-in','typewriter','neon-glow','shimmer-sweep', + 'gradient-flow','stagger-list','counter-up','path-draw','parallax-tilt', + 'card-flip-3d','cube-rotate-3d','page-turn-3d','perspective-zoom', + 'marquee-scroll','kenburns','confetti-burst','spotlight','morph-shape','ripple-reveal']; + + function ready(fn){ if(document.readyState!='loading')fn(); else document.addEventListener('DOMContentLoaded',fn);} + + /* ========== Parse URL for preview-only mode ========== + * When loaded as iframe.src = "index.html?preview=3", runtime enters a + * locked single-slide mode: only slide N is visible, no chrome, no keys, + * no hash updates. This is how the presenter window shows pixel-perfect + * previews — by loading the actual deck file in an iframe and telling it + * to display only a specific slide. + */ + function getPreviewIdx() { + const m = /[?&]preview=(\d+)/.exec(location.search || ''); + return m ? parseInt(m[1], 10) - 1 : -1; + } + + ready(function () { + const deck = document.querySelector('.deck'); + if (!deck) return; + const slides = Array.from(deck.querySelectorAll('.slide')); + if (!slides.length) return; + + const previewOnlyIdx = getPreviewIdx(); + const isPreviewMode = previewOnlyIdx >= 0 && previewOnlyIdx < slides.length; + + /* ===== Preview-only mode: show one slide, hide everything else ===== */ + if (isPreviewMode) { + function showSlide(i) { + slides.forEach((s, j) => { + const active = (j === i); + s.classList.toggle('is-active', active); + s.style.display = active ? '' : 'none'; + if (active) { + s.style.opacity = '1'; + s.style.transform = 'none'; + s.style.pointerEvents = 'auto'; + } + }); + } + showSlide(previewOnlyIdx); + /* Hide chrome that the presenter shouldn't see in preview */ + const hideSel = '.progress-bar, .notes-overlay, .overview, .notes, aside.notes, .speaker-notes'; + document.querySelectorAll(hideSel).forEach(el => { el.style.display = 'none'; }); + document.documentElement.setAttribute('data-preview', '1'); + document.body.setAttribute('data-preview', '1'); + /* Auto-detect theme base path for theme switching in preview mode */ + function getPreviewThemeBase() { + const base = document.documentElement.getAttribute('data-theme-base'); + if (base) return base; + const tl = document.getElementById('theme-link'); + if (tl) { + const raw = tl.getAttribute('href') || ''; + const ls = raw.lastIndexOf('/'); + if (ls >= 0) return raw.substring(0, ls + 1); + } + return 'assets/themes/'; + } + const previewThemeBase = getPreviewThemeBase(); + + /* Listen for postMessage from parent presenter window: + * - preview-goto: switch visible slide WITHOUT reloading + * - preview-theme: switch theme CSS link to match audience window */ + window.addEventListener('message', function(e) { + if (!e.data) return; + if (e.data.type === 'preview-goto') { + const n = parseInt(e.data.idx, 10); + if (n >= 0 && n < slides.length) showSlide(n); + } else if (e.data.type === 'preview-theme' && e.data.name) { + let link = document.getElementById('theme-link'); + if (!link) { + link = document.createElement('link'); + link.rel = 'stylesheet'; + link.id = 'theme-link'; + document.head.appendChild(link); + } + link.href = previewThemeBase + e.data.name + '.css'; + document.documentElement.setAttribute('data-theme', e.data.name); + } + }); + /* Signal to parent that preview iframe is ready */ + try { window.parent && window.parent.postMessage({ type: 'preview-ready' }, '*'); } catch(e) {} + return; + } + + let idx = 0; + const total = slides.length; + + /* ===== BroadcastChannel for presenter sync ===== */ + const CHANNEL_NAME = 'html-ppt-presenter-' + location.pathname; + let bc; + try { bc = new BroadcastChannel(CHANNEL_NAME); } catch(e) { bc = null; } + + // Are we running inside the presenter popup? (legacy flag, now unused) + const isPresenterWindow = false; + + /* ===== progress bar ===== */ + let bar = document.querySelector('.progress-bar'); + if (!bar) { + bar = document.createElement('div'); + bar.className = 'progress-bar'; + bar.innerHTML = ''; + document.body.appendChild(bar); + } + const barFill = bar.querySelector('span'); + + /* ===== notes overlay (N key) ===== */ + let notes = document.querySelector('.notes-overlay'); + if (!notes) { + notes = document.createElement('div'); + notes.className = 'notes-overlay'; + document.body.appendChild(notes); + } + + /* ===== overview grid (O key) ===== */ + let overview = document.querySelector('.overview'); + if (!overview) { + overview = document.createElement('div'); + overview.className = 'overview'; + slides.forEach((s, i) => { + const t = document.createElement('div'); + t.className = 'thumb'; + // Force 16:9 aspect ratio robustly + t.style.padding = '0 0 56.25% 0'; + t.style.height = '0'; + t.style.position = 'relative'; + t.style.overflow = 'hidden'; + + const title = s.getAttribute('data-title') || + (s.querySelector('h1,h2,h3')||{}).textContent || ('Slide '+(i+1)); + + // Create a container for the mini-slide + const mini = document.createElement('div'); + mini.className = 'mini-slide'; + mini.style.position = 'absolute'; + mini.style.top = '0'; + mini.style.left = '0'; + mini.style.width = '1920px'; + mini.style.height = '1080px'; + mini.style.transformOrigin = 'top left'; + mini.style.pointerEvents = 'none'; + mini.style.background = 'var(--bg)'; + + // Clone the slide content + const clone = s.cloneNode(true); + clone.className = 'slide is-active'; // force active styles + clone.style.position = 'absolute'; + clone.style.inset = '0'; + clone.style.transform = 'none'; + clone.style.opacity = '1'; + clone.style.padding = '72px 96px'; // ensure padding is kept + + mini.appendChild(clone); + t.appendChild(mini); + + // Add the number and title overlay + const overlay = document.createElement('div'); + overlay.style.position = 'absolute'; + overlay.style.inset = '0'; + overlay.style.background = 'linear-gradient(to bottom, rgba(0,0,0,0.2) 0%, transparent 40%, transparent 60%, rgba(0,0,0,0.8) 100%)'; + overlay.style.color = '#fff'; + overlay.style.zIndex = '10'; + overlay.style.pointerEvents = 'none'; + + const n = document.createElement('div'); + n.className = 'n'; + n.textContent = i + 1; + n.style.position = 'absolute'; + n.style.top = '12px'; + n.style.left = '16px'; + n.style.fontWeight = '700'; + n.style.fontSize = '16px'; + n.style.color = '#fff'; + n.style.textShadow = '0 1px 4px rgba(0,0,0,0.8)'; + + const text = document.createElement('div'); + text.className = 't'; + text.textContent = title.trim().slice(0,80); + text.style.position = 'absolute'; + text.style.bottom = '12px'; + text.style.left = '16px'; + text.style.right = '16px'; + text.style.fontWeight = '600'; + text.style.fontSize = '14px'; + text.style.color = '#fff'; + text.style.textShadow = '0 1px 4px rgba(0,0,0,0.8)'; + + overlay.appendChild(n); + overlay.appendChild(text); + t.appendChild(overlay); + + t.addEventListener('click', () => { go(i); toggleOverview(false); }); + overview.appendChild(t); + }); + document.body.appendChild(overview); + } + + /* ===== 排版溢出检测 ===== + * 检测 .page-body 内容是否超出可用高度,输出控制台警告。 + * 不自动缩放,避免元素重叠。 + */ + function checkOverflow(n) { + var slide = slides[n]; + if (!slide) return; + var body = slide.querySelector('.page-body'); + if (!body) return; + + var availH = body.clientHeight; + var contentH = body.scrollHeight; + + if (contentH > availH) { + var overflow = contentH - availH; + var pct = ((contentH / availH) - 1) * 100; + var title = slide.getAttribute('data-title') || ('Slide ' + (n + 1)); + console.warn( + '[CCTC 排版警告] 幻灯片 "' + title + '" 内容溢出: ' + + overflow.toFixed(0) + 'px (' + pct.toFixed(0) + '% 超出). ' + + '建议精简内容或拆分到多页。详情见 layout-rules.md' + ); + // 可选:在页面上添加红色边框标记溢出 + body.style.outline = '2px dashed rgba(185,28,28,0.5)'; + } else { + // 清除之前的标记 + var body2 = slide.querySelector('.page-body'); + if (body2 && body2.style.outline) { + body2.style.outline = ''; + } + } + } + + /* ===== navigation ===== */ + function go(n, fromRemote){ + n = Math.max(0, Math.min(total-1, n)); + slides.forEach((s,i) => { + s.classList.toggle('is-active', i===n); + s.classList.toggle('is-prev', i checkOverflow(n)); + + // re-trigger entry animations (skip during fullscreen transition) + if (!document.documentElement.classList.contains('fs-transition')) { + slides[n].querySelectorAll('[data-anim]').forEach(el => { + const a = el.getAttribute('data-anim'); + el.classList.remove('anim-'+a); + void el.offsetWidth; + el.classList.add('anim-'+a); + }); + } + + // counter-up + slides[n].querySelectorAll('.counter').forEach(el => { + const target = parseFloat(el.getAttribute('data-to')||el.textContent); + const dur = parseInt(el.getAttribute('data-dur')||'1200',10); + const start = performance.now(); + const from = 0; + function tick(now){ + const t = Math.min(1,(now-start)/dur); + const v = from + (target-from)*(1-Math.pow(1-t,3)); + el.textContent = (target % 1 === 0) ? Math.round(v) : v.toFixed(1); + if (t<1) requestAnimationFrame(tick); + } + requestAnimationFrame(tick); + }); + + // Broadcast to other window (audience ↔ presenter) + if (!fromRemote && bc) { + bc.postMessage({ type: 'go', idx: n }); + } + } + + /* ===== listen for remote navigation / theme changes ===== */ + if (bc) { + bc.onmessage = function(e) { + if (!e.data) return; + if (e.data.type === 'go' && typeof e.data.idx === 'number') { + go(e.data.idx, true); + } else if (e.data.type === 'theme' && e.data.name) { + /* Sync theme across windows */ + const i = themes.indexOf(e.data.name); + if (i >= 0) themeIdx = i; + applyTheme(e.data.name); + } + }; + } + + function toggleNotes(force){ notes.classList.toggle('open', force!==undefined?force:!notes.classList.contains('open')); } + function toggleOverview(force){ + const isOpen = force!==undefined ? force : !overview.classList.contains('open'); + overview.classList.toggle('open', isOpen); + if (isOpen) { + requestAnimationFrame(() => { + const thumbs = overview.querySelectorAll('.thumb'); + if (thumbs.length) { + const scale = thumbs[0].clientWidth / 1920; + overview.querySelectorAll('.mini-slide').forEach(m => { + m.style.transform = 'scale(' + scale + ')'; + }); + } + }); + } + } + + /* ========== PRESENTER MODE — Magnetic-card popup window ========== */ + /* Opens a new window with 4 draggable, resizable cards: + * CURRENT — iframe(?preview=N) pixel-perfect preview of current slide + * NEXT — iframe(?preview=N+1) pixel-perfect preview of next slide + * SCRIPT — large speaker notes (逐字稿) + * TIMER — elapsed timer + page counter + controls + * Cards remember position/size in localStorage. + * Two windows sync via BroadcastChannel. + */ + let presenterWin = null; + + function openPresenterWindow() { + if (presenterWin && !presenterWin.closed) { + presenterWin.focus(); + return; + } + + // Build absolute URL of THIS deck file (without hash/query) + const deckUrl = location.protocol + '//' + location.host + location.pathname; + + // Collect slide titles + notes (HTML strings) + const slideMeta = slides.map((s, i) => { + const note = s.querySelector('.notes, aside.notes, .speaker-notes'); + return { + title: s.getAttribute('data-title') || + (s.querySelector('h1,h2,h3')||{}).textContent || ('Slide '+(i+1)), + notes: note ? note.innerHTML : '' + }; + }); + + /* Capture current theme so presenter previews match the audience */ + const currentTheme = root.getAttribute('data-theme') || (themes[themeIdx] || ''); + const presenterHTML = buildPresenterHTML(deckUrl, slideMeta, total, idx, CHANNEL_NAME, currentTheme); + + presenterWin = window.open('', 'html-ppt-presenter', 'width=1280,height=820,menubar=no,toolbar=no'); + if (!presenterWin) { + alert('请允许弹出窗口以使用演讲者视图'); + return; + } + presenterWin.document.open(); + presenterWin.document.write(presenterHTML); + presenterWin.document.close(); + } + + function buildPresenterHTML(deckUrl, slideMeta, total, startIdx, channelName, currentTheme) { + const metaJSON = JSON.stringify(slideMeta); + const deckUrlJSON = JSON.stringify(deckUrl); + const channelJSON = JSON.stringify(channelName); + const themeJSON = JSON.stringify(currentTheme || ''); + const storageKey = 'html-ppt-presenter:' + location.pathname; + + // Build the document as a single template string for clarity + return ` + + + +Presenter View + + + + +
+
+
+ + CURRENT + — +
+
+
+
+ +
+
+ + NEXT + — +
+
+
+
+ +
+
+ + SPEAKER SCRIPT · 逐字稿 +
+
+
+
+ +
+
+ + TIMER +
+
+
00:00
+
+ Slide + 1 / ${total} +
+
+ + + +
+
+
+
+
+ +
+ ← → 翻页 + R 重置计时 + Esc 关闭 + 拖动卡片头部移动 · 拖动右下角调整大小 + +
+ + + + diff --git a/pres/bps-schema-intro.pdf b/pres/bps-schema-intro.pdf new file mode 100644 index 0000000..c7a07fd Binary files /dev/null and b/pres/bps-schema-intro.pdf differ diff --git a/pres/slide-01.jpg b/pres/slide-01.jpg new file mode 100644 index 0000000..174fbb3 Binary files /dev/null and b/pres/slide-01.jpg differ diff --git a/pres/slide-02.jpg b/pres/slide-02.jpg new file mode 100644 index 0000000..a96ab28 Binary files /dev/null and b/pres/slide-02.jpg differ diff --git a/pres/slide-03.jpg b/pres/slide-03.jpg new file mode 100644 index 0000000..a833437 Binary files /dev/null and b/pres/slide-03.jpg differ diff --git a/pres/slide-04.jpg b/pres/slide-04.jpg new file mode 100644 index 0000000..c8c8500 Binary files /dev/null and b/pres/slide-04.jpg differ diff --git a/pres/slide-05.jpg b/pres/slide-05.jpg new file mode 100644 index 0000000..ff2de0c Binary files /dev/null and b/pres/slide-05.jpg differ diff --git a/pres/slide-06.jpg b/pres/slide-06.jpg new file mode 100644 index 0000000..8e06435 Binary files /dev/null and b/pres/slide-06.jpg differ diff --git a/pres/slide-07.jpg b/pres/slide-07.jpg new file mode 100644 index 0000000..bcd614c Binary files /dev/null and b/pres/slide-07.jpg differ diff --git a/pres/slide-08.jpg b/pres/slide-08.jpg new file mode 100644 index 0000000..dbed4ea Binary files /dev/null and b/pres/slide-08.jpg differ diff --git a/pres/slide-09.jpg b/pres/slide-09.jpg new file mode 100644 index 0000000..9841d7d Binary files /dev/null and b/pres/slide-09.jpg differ diff --git a/pres/slide-10.jpg b/pres/slide-10.jpg new file mode 100644 index 0000000..8c69155 Binary files /dev/null and b/pres/slide-10.jpg differ diff --git a/pres/slide-11.jpg b/pres/slide-11.jpg new file mode 100644 index 0000000..bb81b8e Binary files /dev/null and b/pres/slide-11.jpg differ diff --git a/pres/slide-12.jpg b/pres/slide-12.jpg new file mode 100644 index 0000000..cecec79 Binary files /dev/null and b/pres/slide-12.jpg differ diff --git a/pres/slide-13.jpg b/pres/slide-13.jpg new file mode 100644 index 0000000..537c6a7 Binary files /dev/null and b/pres/slide-13.jpg differ diff --git a/pres/slide-14.jpg b/pres/slide-14.jpg new file mode 100644 index 0000000..52eb27a Binary files /dev/null and b/pres/slide-14.jpg differ diff --git a/pres/slide-15.jpg b/pres/slide-15.jpg new file mode 100644 index 0000000..b377d13 Binary files /dev/null and b/pres/slide-15.jpg differ diff --git a/pres/slide-16.jpg b/pres/slide-16.jpg new file mode 100644 index 0000000..4b54b46 Binary files /dev/null and b/pres/slide-16.jpg differ diff --git a/schema-all.json b/schema-all.json new file mode 100644 index 0000000..89e8cd1 --- /dev/null +++ b/schema-all.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "bps/all", + "title": "All-Scale Schema Aggregation", + "description": "Aggregation entry point that references all scale-specific schemas organized by geometry and simulation domain.", + "$defs": { + "building": { + "$ref": "./schema-building.json" + }, + "energy": { + "$ref": "./schema-energy.json" + }, + "radiance": { + "$ref": "./schema-radiance.json" + }, + "cfd": { + "$ref": "./schema-cfd.json" + }, + "community": { + "$ref": "./schema-community.json" + }, + "community-energy": { + "$ref": "./schema-community-energy.json" + }, + "community-cfd": { + "$ref": "./schema-community-cfd.json" + }, + "community-microclimate": { + "$ref": "./schema-community-microclimate.json" + }, + "urban": { + "$ref": "./schema-urban.json" + }, + "urban-energy": { + "$ref": "./schema-urban-energy.json" + }, + "urban-cfd": { + "$ref": "./schema-urban-cfd.json" + } + } +} \ No newline at end of file diff --git a/schema-building.json b/schema-building.json index 01323a9..530ccae 100644 --- a/schema-building.json +++ b/schema-building.json @@ -1,388 +1,962 @@ { - "archgen": { - "version": "0.1.0", - "description": "ArchGen Schema — 建筑几何与核心实体", - "tags": { - "scale": { - "building": "建筑尺度", - "community": "社区/街区尺度", - "urban": "城市尺度" - }, - "simulation": { - "energy": "能耗模拟", - "daylight": "采光分析", - "solar": "日照分析", - "thermal_comfort": "热舒适分析", - "carbon": "碳排放核算", - "wind": "风环境模拟", - "general": "通用(不特定于某种模拟)" - } - } - }, - - "types": { - "Point3d": { - "description": "三维点坐标", - "fields": { - "x": { "type": "number", "default": 0 }, - "y": { "type": "number", "default": 0 }, - "z": { "type": "number", "default": 0 } - } - }, - "Polyline3d": { - "description": "三维多段线(点列表)", - "fields": { - "points": { "type": "Point3d[]", "default": [] } - } - }, - "Vector3d": { - "description": "三维向量", - "fields": { - "x": { "type": "number", "default": 0 }, - "y": { "type": "number", "default": 0 }, - "z": { "type": "number", "default": 0 } - } - }, - "Line3d": { - "description": "直线(起点+终点)", - "fields": { - "from": { "type": "Point3d" }, - "to": { "type": "Point3d" } - } - }, - "TimePoint": { - "description": "时刻点 [时, 分]", - "fields": { - "hour": { "type": "integer", "default": 0 }, - "minute": { "type": "integer", "default": 0 } - } - }, - "DatePoint": { - "description": "日期点 [月, 日]", - "fields": { - "month": { "type": "integer", "default": 1 }, - "day": { "type": "integer", "default": 1 } - } - }, - "Period": { - "description": "时间范围", - "fields": { - "start": { "type": "DatePoint" }, - "end": { "type": "DatePoint" } - } - }, - "UVRect": { - "description": "UV 矩形坐标 [u, v, 宽比, 高比]", - "fields": { - "u": { "type": "number" }, - "v": { "type": "number" }, - "widthRatio": { "type": "number" }, - "heightRatio": { "type": "number" } - } - } - }, - - "enums": { - "Direction": { - "description": "朝向", - "values": ["N", "NE", "E", "SE", "S", "SW", "W", "NW"] - }, - "BoundaryType": { - "description": "边界类型", - "values": [ - "exterior_wall", "interior_wall", "curtain_wall", - "roof", "floor", "slab", "foundation" - ] - }, - "ElementType": { - "description": "结构构件类型", - "values": [ - "column", "beam", "slab", "wall", - "foundation", "stair", "ramp" - ] - }, - "ApertureGeometryType": { - "description": "洞口几何类型", - "values": ["window", "door", "curtain_wall", "generic"] - }, - "ApertureContextType": { - "description": "洞口内外上下文", - "values": ["EXTERIOR", "INTERIOR"] - }, - "RoomCreationMethod": { - "description": "房间创建方式", - "values": ["planar_extrude", "mass_slice", "manual"] - }, - "RelationType": { - "description": "拓扑关系类型", - "values": ["adjacent", "contains", "crosses", "flows", "touches", "sight"] - } - }, - - "entities": { - "Building": { - "description": "建筑顶级实体", - "tags": { "scale": ["building", "community", "urban"] }, - "attributes": { - "identifier": { "type": "string", "required": true, "description": "唯一标识符", "tags": { "simulation": ["general"] } }, - "displayName": { "type": "string", "description": "显示名称", "tags": { "simulation": ["general"] } }, - "schemaVersion": { "type": "string", "required": true, "description": "archgen-schema 版本", "tags": { "simulation": ["general"] } }, - "siteBasePoint": { "type": "Point3d", "required": true, "description": "建筑基准点", "tags": { "simulation": ["general"] } }, - "northAngle": { "type": "number", "required": true, "default": 0, "description": "建筑正北角度", "tags": { "simulation": ["energy", "daylight", "solar", "thermal_comfort", "wind"] } }, - "globalSettings": { "type": "object", "description": "全局设置", "tags": { "simulation": ["general"] } }, - "metadata": { "type": "object", "description": "自定义元数据", "tags": { "simulation": ["general"] } } - }, - "children": { - "floors": { "type": "Floor", "multiple": true, "description": "楼层列表", "tags": { "scale": ["building", "community"], "simulation": ["general"] } }, - "masses": { "type": "MassEntity", "multiple": true, "description": "参数化体量", "tags": { "scale": ["building"], "simulation": ["general"] } }, - "shafts": { "type": "Shaft", "multiple": true, "description": "竖井", "tags": { "scale": ["building"], "simulation": ["general"] } }, - "shades": { "type": "Shade", "multiple": true, "description": "遮阳", "tags": { "scale": ["building", "community"], "simulation": ["energy", "daylight", "solar", "thermal_comfort"] } }, - "siteShades": { "type": "Shade", "multiple": true, "description": "外部遮阳(树木、邻楼)", "tags": { "scale": ["building", "community", "urban"], "simulation": ["energy", "daylight", "solar", "wind"] } }, - "gridSystem": { "type": "GridSystem", "description": "轴网系统", "tags": { "scale": ["building"], "simulation": ["general"] } }, - "relations": { "type": "Relation", "multiple": true, "description": "拓扑关系", "tags": { "scale": ["building", "community", "urban"], "simulation": ["general"] } } - } - }, - - "Floor": { - "description": "楼层", - "tags": { "scale": ["building", "community"] }, - "attributes": { - "identifier": { "type": "string", "required": true, "description": "唯一标识符", "tags": { "simulation": ["general"] } }, - "displayName": { "type": "string", "description": "显示名称", "tags": { "simulation": ["general"] } }, - "elevation": { "type": "number", "required": true, "description": "楼层标高 Z", "tags": { "simulation": ["general"] } }, - "height": { "type": "number", "required": true, "description": "层高", "unit": "m", "tags": { "simulation": ["energy", "daylight", "thermal_comfort", "carbon"] } }, - "story": { "type": "integer", "required": true, "description": "楼层序号", "tags": { "simulation": ["general"] } }, - "outline": { "type": "Polyline3d", "description": "楼板轮廓", "tags": { "simulation": ["general"] } }, - "metadata": { "type": "object", "tags": { "simulation": ["general"] } } - }, - "children": { - "rooms": { "type": "Room", "multiple": true, "description": "房间" }, - "apertures": { "type": "Aperture", "multiple": true, "description": "楼层级洞口", "tags": { "scale": ["building"], "simulation": ["energy", "daylight", "wind"] } }, - "elements": { "type": "Element", "multiple": true, "description": "结构构件", "tags": { "scale": ["building"], "simulation": ["general"] } } - } - }, - - "Room": { - "description": "房间", - "tags": { "scale": ["building", "community"] }, - "discriminator": "creationMethod", - "variants": { - "planar_extrude": { - "description": "平面轮廓拉伸创建", - "attributes": { - "identifier": { "type": "string", "required": true, "tags": { "simulation": ["general"] } }, - "displayName": { "type": "string", "tags": { "simulation": ["general"] } }, - "creationMethod": { "type": "RoomCreationMethod", "required": true, "default": "planar_extrude", "tags": { "simulation": ["general"] } }, - "programType": { "type": "string", "description": "房间功能类型", "tags": { "scale": ["building"], "simulation": ["energy", "thermal_comfort", "carbon"] } }, - "region": { "type": "Polyline3d", "required": true, "description": "房间轮廓", "tags": { "simulation": ["energy", "daylight", "solar", "wind", "thermal_comfort"] } }, - "height": { "type": "number", "required": true, "description": "房间高度", "tags": { "simulation": ["energy", "daylight", "thermal_comfort"] } }, - "elevation": { "type": "number", "description": "楼层内 Z 偏移", "tags": { "simulation": ["general"] } }, - "boundaries": { "type": "Boundary[]", "description": "房间边界/墙体", "tags": { "simulation": ["energy", "thermal_comfort"] } }, - "apertures": { "type": "string[]", "description": "关联洞口 ID 列表", "tags": { "scale": ["building"], "simulation": ["energy", "daylight", "wind"] } }, - "elements": { "type": "Element[]", "description": "房间内构件", "tags": { "scale": ["building"], "simulation": ["general"] } }, - "geometryDriver": { "type": "object", "description": "几何驱动参数", "tags": { "simulation": ["general"] } }, - "metadata": { "type": "object", "tags": { "simulation": ["general"] } } - } + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "bps/building", + "title": "HBJSON Compatible Building Schema", + "description": "Building-scale geometry schema, fully compatible with honeybee-schema (HBJSON). Defines the core hierarchy: Model \u2192 Room \u2192 Face \u2192 Aperture/Door \u2192 Shade.", + "$defs": { + "Point3D": { + "type": "object", + "properties": { + "type": { + "const": "Point3D" }, - "mass_slice": { - "description": "体量切片创建", - "attributes": { - "identifier": { "type": "string", "required": true, "tags": { "simulation": ["general"] } }, - "displayName": { "type": "string", "tags": { "simulation": ["general"] } }, - "creationMethod": { "type": "RoomCreationMethod", "required": true, "default": "mass_slice", "tags": { "simulation": ["general"] } }, - "programType": { "type": "string", "tags": { "scale": ["building"], "simulation": ["energy", "thermal_comfort", "carbon"] } }, - "region": { "type": "Polyline3d", "required": true, "tags": { "simulation": ["energy", "daylight", "solar", "wind", "thermal_comfort"] } }, - "height": { "type": "number", "required": true, "tags": { "simulation": ["energy", "daylight", "thermal_comfort"] } }, - "elevation": { "type": "number", "tags": { "simulation": ["general"] } }, - "boundaries": { "type": "Boundary[]", "tags": { "simulation": ["energy", "thermal_comfort"] } }, - "apertures": { "type": "string[]", "tags": { "scale": ["building"], "simulation": ["energy", "daylight", "wind"] } }, - "elements": { "type": "Element[]", "tags": { "scale": ["building"], "simulation": ["general"] } }, - "driverRef": { - "type": "object", "required": true, "description": "体量引用", - "tags": { "simulation": ["general"] }, - "attributes": { - "massId": { "type": "string", "required": true }, - "sliceZ": { "type": "number", "required": true } - } + "x": { + "type": "number" + }, + "y": { + "type": "number" + }, + "z": { + "type": "number" + } + }, + "required": [ + "x", + "y", + "z" + ], + "additionalProperties": false + }, + "Plane": { + "type": "object", + "properties": { + "type": { + "const": "Plane" + }, + "n": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3 + }, + "o": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3 + }, + "x": { + "type": [ + "array", + "null" + ], + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3 + } + }, + "required": [ + "n", + "o" + ], + "additionalProperties": false + }, + "Face3D": { + "type": "object", + "properties": { + "type": { + "const": "Face3D" + }, + "boundary": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "number" }, - "metadata": { "type": "object", "tags": { "simulation": ["general"] } } + "minItems": 3, + "maxItems": 3 + }, + "minItems": 3 + }, + "holes": { + "type": [ + "array", + "null" + ], + "items": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3 + }, + "minItems": 3 } }, - "manual": { - "description": "手动绘制", - "attributes": { - "identifier": { "type": "string", "required": true, "tags": { "simulation": ["general"] } }, - "displayName": { "type": "string", "tags": { "simulation": ["general"] } }, - "creationMethod": { "type": "RoomCreationMethod", "required": true, "default": "manual", "tags": { "simulation": ["general"] } }, - "programType": { "type": "string", "tags": { "scale": ["building"], "simulation": ["energy", "thermal_comfort", "carbon"] } }, - "region": { "type": "Polyline3d", "required": true, "tags": { "simulation": ["energy", "daylight", "solar", "wind", "thermal_comfort"] } }, - "height": { "type": "number", "required": true, "tags": { "simulation": ["energy", "daylight", "thermal_comfort"] } }, - "elevation": { "type": "number", "tags": { "simulation": ["general"] } }, - "boundaries": { "type": "Boundary[]", "tags": { "simulation": ["energy", "thermal_comfort"] } }, - "apertures": { "type": "string[]", "tags": { "scale": ["building"], "simulation": ["energy", "daylight", "wind"] } }, - "elements": { "type": "Element[]", "tags": { "scale": ["building"], "simulation": ["general"] } }, - "metadata": { "type": "object", "tags": { "simulation": ["general"] } } + "plane": { + "anyOf": [ + { + "$ref": "#/$defs/Plane" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "boundary" + ], + "additionalProperties": false + }, + "Color": { + "type": "object", + "properties": { + "type": { + "const": "Color" + }, + "r": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "g": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "b": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "a": { + "type": "integer", + "minimum": 0, + "maximum": 255, + "default": 255 + } + }, + "required": [ + "r", + "g", + "b" + ], + "additionalProperties": false + }, + "Mesh3D": { + "type": "object", + "properties": { + "type": { + "const": "Mesh3D" + }, + "vertices": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3 + }, + "minItems": 3 + }, + "faces": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "integer", + "minimum": 0 + }, + "minItems": 3, + "maxItems": 4 + }, + "minItems": 1 + }, + "colors": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/$defs/Color" } } - } + }, + "required": [ + "vertices", + "faces" + ], + "additionalProperties": false }, - - "Aperture": { - "description": "建筑洞口", - "tags": { "scale": ["building"], "simulation": ["energy", "daylight", "solar", "wind"] }, - "discriminator": "sourceType", - "variants": { - "hosted": { - "description": "绑定到特定形体面", - "attributes": { - "identifier": { "type": "string", "required": true, "tags": { "simulation": ["general"] } }, - "displayName": { "type": "string", "tags": { "simulation": ["general"] } }, - "sourceType": { "type": "string", "required": true, "default": "hosted", "tags": { "simulation": ["general"] } }, - "geometryType": { "type": "ApertureGeometryType", "required": true, "tags": { "simulation": ["energy", "daylight", "solar", "wind"] } }, - "width": { "type": "number", "tags": { "simulation": ["energy", "daylight"] } }, - "height": { "type": "number", "tags": { "simulation": ["energy", "daylight"] } }, - "sillHeight": { "type": "number", "description": "窗台高", "tags": { "simulation": ["energy", "daylight"] } }, - "parent": { "type": "string", "description": "父实体 ID", "tags": { "simulation": ["general"] } }, - "rooms": { "type": "string[]", "description": "相邻房间 ID", "tags": { "simulation": ["energy", "thermal_comfort"] } }, - "openRatio": { "type": "number", "default": 0, "description": "开启比", "tags": { "simulation": ["energy", "wind", "thermal_comfort"] } }, - "operable": { "type": "boolean", "default": false, "tags": { "simulation": ["energy", "wind", "thermal_comfort"] } }, - "hosting": { - "type": "object", "required": true, "description": "宿主绑定信息", - "tags": { "simulation": ["general"] }, - "attributes": { - "hostId": { "type": "string", "required": true }, - "faceIndex": { "type": "integer", "required": true }, - "uvRect": { "type": "UVRect", "required": true }, - "context": { "type": "ApertureContextType", "required": true } - } - }, - "metadata": { "type": "object", "tags": { "simulation": ["general"] } } - } + "UserData": { + "type": [ + "object", + "null" + ], + "description": "Optional dictionary of user data. All keys and values should be standard data types." + }, + "_IdentifiedObject": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "pattern": "^[.A-Za-z0-9_-]+$", + "minLength": 1, + "maxLength": 100 }, - "declarative": { - "description": "声明式放置", - "attributes": { - "identifier": { "type": "string", "required": true, "tags": { "simulation": ["general"] } }, - "displayName": { "type": "string", "tags": { "simulation": ["general"] } }, - "sourceType": { "type": "string", "required": true, "default": "declarative", "tags": { "simulation": ["general"] } }, - "geometryType": { "type": "ApertureGeometryType", "required": true, "tags": { "simulation": ["energy", "daylight", "solar", "wind"] } }, - "width": { "type": "number", "tags": { "simulation": ["energy", "daylight"] } }, - "height": { "type": "number", "tags": { "simulation": ["energy", "daylight"] } }, - "sillHeight": { "type": "number", "tags": { "simulation": ["energy", "daylight"] } }, - "parent": { "type": "string", "tags": { "simulation": ["general"] } }, - "rooms": { "type": "string[]", "tags": { "simulation": ["energy", "thermal_comfort"] } }, - "openRatio": { "type": "number", "default": 0, "tags": { "simulation": ["energy", "wind", "thermal_comfort"] } }, - "operable": { "type": "boolean", "default": false, "tags": { "simulation": ["energy", "wind", "thermal_comfort"] } }, - "placement": { - "type": "object", "description": "放置描述", - "tags": { "simulation": ["general"] }, - "attributes": { - "boundaryId": { "type": "string" }, - "position": { "type": "string", "description": "center, start, end 或距离" }, - "orientation": { "type": "Direction" } - } - }, - "metadata": { "type": "object", "tags": { "simulation": ["general"] } } - } + "display_name": { + "type": [ + "string", + "null" + ], + "default": null + }, + "user_data": { + "$ref": "#/$defs/UserData" } - } + }, + "required": [ + "identifier" + ] }, - - "Boundary": { - "description": "空间边界/墙体", - "tags": { "scale": ["building", "community"], "simulation": ["energy", "thermal_comfort", "carbon"] }, - "attributes": { - "identifier": { "type": "string", "required": true, "tags": { "simulation": ["general"] } }, - "displayName": { "type": "string", "tags": { "simulation": ["general"] } }, - "type": { "type": "BoundaryType", "required": true, "tags": { "simulation": ["energy", "thermal_comfort", "carbon"] } }, - "region": { "type": "Polyline3d", "required": true, "description": "边界线段或多边形", "tags": { "simulation": ["energy", "thermal_comfort"] } }, - "thickness": { "type": "number", "description": "墙厚", "unit": "m", "tags": { "scale": ["building"], "simulation": ["energy", "thermal_comfort", "carbon"] } }, - "height": { "type": "number", "description": "墙高", "unit": "m", "tags": { "simulation": ["energy", "thermal_comfort"] } }, - "direction": { "type": "Direction", "description": "朝向", "tags": { "simulation": ["energy", "daylight", "solar"] } }, - "pitch": { "type": "number", "description": "倾斜角度", "unit": "deg", "tags": { "simulation": ["energy", "solar"] } }, - "hostRoomId": { "type": "string", "description": "所属房间 ID", "tags": { "simulation": ["general"] } }, - "constructionId": { "type": "string", "description": "构造 ID", "tags": { "simulation": ["energy", "thermal_comfort", "carbon"] } }, - "sharedBy": { "type": "string[]", "description": "共享此边界的房间 ID 列表", "tags": { "simulation": ["thermal_comfort"] } }, - "metadata": { "type": "object", "tags": { "simulation": ["general"] } } - } + "Outdoors": { + "type": "object", + "properties": { + "type": { + "const": "Outdoors" + }, + "sun_exposure": { + "type": "boolean", + "default": true + }, + "wind_exposure": { + "type": "boolean", + "default": true + }, + "view_factor": { + "anyOf": [ + { + "type": "number" + }, + { + "const": "autocalculate" + } + ], + "default": "autocalculate" + } + }, + "required": [ + "type" + ], + "additionalProperties": false }, - - "Element": { - "description": "结构构件", - "tags": { "scale": ["building"] }, - "attributes": { - "identifier": { "type": "string", "required": true, "tags": { "simulation": ["general"] } }, - "displayName": { "type": "string", "tags": { "simulation": ["general"] } }, - "type": { "type": "ElementType", "required": true, "tags": { "simulation": ["general"] } }, - "region": { "type": "Polyline3d", "description": "截面轮廓", "tags": { "simulation": ["general"] } }, - "height": { "type": "number", "unit": "m", "tags": { "simulation": ["general"] } }, - "materialId": { "type": "string", "description": "材料 ID", "tags": { "simulation": ["carbon"] } }, - "metadata": { "type": "object", "tags": { "simulation": ["general"] } } - } + "Surface": { + "type": "object", + "properties": { + "type": { + "const": "Surface" + }, + "boundary_condition_objects": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 2, + "maxItems": 3 + } + }, + "required": [ + "type", + "boundary_condition_objects" + ], + "additionalProperties": false }, - - "MassEntity": { - "description": "参数化体量", - "tags": { "scale": ["building"] }, - "attributes": { - "identifier": { "type": "string", "required": true, "tags": { "simulation": ["general"] } }, - "displayName": { "type": "string", "tags": { "simulation": ["general"] } }, - "region": { "type": "Polyline3d", "tags": { "simulation": ["general"] } }, - "height": { "type": "number", "unit": "m", "tags": { "simulation": ["general"] } }, - "metadata": { "type": "object", "tags": { "simulation": ["general"] } } - } + "Ground": { + "type": "object", + "properties": { + "type": { + "const": "Ground" + } + }, + "required": [ + "type" + ], + "additionalProperties": false }, - - "Shaft": { - "description": "竖井(楼梯/电梯/管道)", - "tags": { "scale": ["building"] }, - "attributes": { - "identifier": { "type": "string", "required": true, "tags": { "simulation": ["general"] } }, - "displayName": { "type": "string", "tags": { "simulation": ["general"] } }, - "type": { "type": "string", "description": "stair/elevator/duct", "tags": { "simulation": ["general"] } }, - "spanLevels": { "type": "string[]", "description": "穿越的楼层 ID", "tags": { "simulation": ["general"] } }, - "region": { "type": "Polyline3d", "description": "竖井截面", "tags": { "simulation": ["general"] } }, - "metadata": { "type": "object", "tags": { "simulation": ["general"] } } - } + "Adiabatic": { + "type": "object", + "properties": { + "type": { + "const": "Adiabatic" + } + }, + "required": [ + "type" + ], + "additionalProperties": false + }, + "OtherSideTemperature": { + "type": "object", + "properties": { + "type": { + "const": "OtherSideTemperature" + }, + "heat_transfer_coefficient": { + "type": "number", + "minimum": 0, + "default": 0 + }, + "temperature": { + "anyOf": [ + { + "type": "number" + }, + { + "const": "autocalculate" + } + ], + "default": "autocalculate" + } + }, + "required": [ + "type" + ], + "additionalProperties": false + }, + "BoundaryCondition": { + "description": "Face boundary condition: Outdoors, Surface, Ground, Adiabatic, or OtherSideTemperature.", + "oneOf": [ + { + "$ref": "#/$defs/Outdoors" + }, + { + "$ref": "#/$defs/Surface" + }, + { + "$ref": "#/$defs/Ground" + }, + { + "$ref": "#/$defs/Adiabatic" + }, + { + "$ref": "#/$defs/OtherSideTemperature" + } + ] + }, + "ApertureBoundaryCondition": { + "description": "Aperture/Door boundary condition: Outdoors or Surface only.", + "oneOf": [ + { + "$ref": "#/$defs/Outdoors" + }, + { + "$ref": "#/$defs/Surface" + } + ] + }, + "FaceType": { + "type": "string", + "enum": [ + "Wall", + "Floor", + "RoofCeiling", + "AirBoundary" + ] + }, + "Units": { + "type": "string", + "enum": [ + "Meters", + "Millimeters", + "Feet", + "Inches", + "Centimeters" + ], + "default": "Meters" + }, + "ShadePropertiesAbridged": { + "type": "object", + "properties": { + "type": { + "const": "ShadePropertiesAbridged" + }, + "energy": { + "type": [ + "object", + "null" + ] + }, + "radiance": { + "type": [ + "object", + "null" + ] + } + }, + "additionalProperties": false }, - "Shade": { - "description": "遮阳构件", - "tags": { "scale": ["building", "community"], "simulation": ["energy", "daylight", "solar", "thermal_comfort"] }, - "attributes": { - "identifier": { "type": "string", "required": true, "tags": { "simulation": ["general"] } }, - "displayName": { "type": "string", "tags": { "simulation": ["general"] } }, - "region": { "type": "Polyline3d", "description": "遮阳轮廓", "tags": { "simulation": ["energy", "daylight", "solar", "thermal_comfort"] } }, - "height": { "type": "number", "unit": "m", "tags": { "simulation": ["energy", "daylight", "solar"] } }, - "transmittance": { "type": "number", "default": 0, "description": "透射率 0-1", "tags": { "simulation": ["energy", "daylight", "solar"] } }, - "metadata": { "type": "object", "tags": { "simulation": ["general"] } } - } + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "Shade" + }, + "geometry": { + "$ref": "#/$defs/Face3D" + }, + "properties": { + "$ref": "#/$defs/ShadePropertiesAbridged" + }, + "is_detached": { + "type": "boolean", + "default": false + } + }, + "required": [ + "type", + "geometry", + "properties" + ], + "additionalProperties": false + } + ] }, - - "GridSystem": { - "description": "轴网系统", - "tags": { "scale": ["building"] }, - "attributes": { - "identifier": { "type": "string", "required": true, "tags": { "simulation": ["general"] } }, - "displayName": { "type": "string", "tags": { "simulation": ["general"] } }, - "axisX": { "type": "string[]", "description": "X 向轴线名", "tags": { "simulation": ["general"] } }, - "axisY": { "type": "string[]", "description": "Y 向轴线名", "tags": { "simulation": ["general"] } }, - "spacingsX": { "type": "number[]", "description": "X 向跨距", "unit": "m", "tags": { "simulation": ["general"] } }, - "spacingsY": { "type": "number[]", "description": "Y 向跨距", "unit": "m", "tags": { "simulation": ["general"] } }, - "origin": { "type": "Point3d", "required": true, "description": "轴网原点", "tags": { "simulation": ["general"] } }, - "metadata": { "type": "object", "tags": { "simulation": ["general"] } } - } + "AperturePropertiesAbridged": { + "type": "object", + "properties": { + "type": { + "const": "AperturePropertiesAbridged" + }, + "energy": { + "type": [ + "object", + "null" + ] + }, + "radiance": { + "type": [ + "object", + "null" + ] + } + }, + "additionalProperties": false }, - - "Relation": { - "description": "拓扑关系边", - "tags": { "scale": ["building", "community", "urban"] }, - "attributes": { - "type": { "type": "RelationType", "required": true, "tags": { "simulation": ["general"] } }, - "source": { "type": "string", "required": true, "description": "源实体 ID", "tags": { "simulation": ["general"] } }, - "target": { "type": "string", "required": true, "description": "目标实体 ID", "tags": { "simulation": ["general"] } }, - "metadata": { "type": "object", "tags": { "simulation": ["general"] } } - } + "Aperture": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "Aperture" + }, + "geometry": { + "$ref": "#/$defs/Face3D" + }, + "boundary_condition": { + "$ref": "#/$defs/ApertureBoundaryCondition" + }, + "is_operable": { + "type": "boolean", + "default": false + }, + "indoor_shades": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/$defs/Shade" + } + }, + "outdoor_shades": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/$defs/Shade" + } + }, + "properties": { + "$ref": "#/$defs/AperturePropertiesAbridged" + } + }, + "required": [ + "type", + "geometry", + "boundary_condition", + "properties" + ], + "additionalProperties": false + } + ] + }, + "DoorPropertiesAbridged": { + "type": "object", + "properties": { + "type": { + "const": "DoorPropertiesAbridged" + }, + "energy": { + "type": [ + "object", + "null" + ] + }, + "radiance": { + "type": [ + "object", + "null" + ] + } + }, + "additionalProperties": false + }, + "Door": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "Door" + }, + "geometry": { + "$ref": "#/$defs/Face3D" + }, + "boundary_condition": { + "$ref": "#/$defs/ApertureBoundaryCondition" + }, + "is_glass": { + "type": "boolean", + "default": false + }, + "indoor_shades": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/$defs/Shade" + } + }, + "outdoor_shades": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/$defs/Shade" + } + }, + "properties": { + "$ref": "#/$defs/DoorPropertiesAbridged" + } + }, + "required": [ + "type", + "geometry", + "boundary_condition", + "properties" + ], + "additionalProperties": false + } + ] + }, + "FacePropertiesAbridged": { + "type": "object", + "properties": { + "type": { + "const": "FacePropertiesAbridged" + }, + "energy": { + "type": [ + "object", + "null" + ] + }, + "radiance": { + "type": [ + "object", + "null" + ] + } + }, + "additionalProperties": false + }, + "Face": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "Face" + }, + "geometry": { + "$ref": "#/$defs/Face3D" + }, + "face_type": { + "$ref": "#/$defs/FaceType" + }, + "boundary_condition": { + "$ref": "#/$defs/BoundaryCondition" + }, + "apertures": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/$defs/Aperture" + } + }, + "doors": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/$defs/Door" + } + }, + "indoor_shades": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/$defs/Shade" + } + }, + "outdoor_shades": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/$defs/Shade" + } + }, + "properties": { + "$ref": "#/$defs/FacePropertiesAbridged" + } + }, + "required": [ + "type", + "geometry", + "face_type", + "boundary_condition", + "properties" + ], + "additionalProperties": false + } + ] + }, + "ShadeMeshPropertiesAbridged": { + "type": "object", + "properties": { + "type": { + "const": "ShadeMeshPropertiesAbridged" + }, + "energy": { + "type": [ + "object", + "null" + ] + }, + "radiance": { + "type": [ + "object", + "null" + ] + } + }, + "additionalProperties": false + }, + "ShadeMesh": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "ShadeMesh" + }, + "geometry": { + "$ref": "#/$defs/Mesh3D" + }, + "properties": { + "$ref": "#/$defs/ShadeMeshPropertiesAbridged" + }, + "is_detached": { + "type": "boolean", + "default": true + } + }, + "required": [ + "type", + "geometry", + "properties" + ], + "additionalProperties": false + } + ] + }, + "RoomPropertiesAbridged": { + "type": "object", + "properties": { + "type": { + "const": "RoomPropertiesAbridged" + }, + "energy": { + "type": [ + "object", + "null" + ] + }, + "radiance": { + "type": [ + "object", + "null" + ] + }, + "doe2": { + "type": [ + "object", + "null" + ] + } + }, + "additionalProperties": false + }, + "Room": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "Room" + }, + "faces": { + "type": "array", + "items": { + "$ref": "#/$defs/Face" + }, + "minItems": 4 + }, + "indoor_shades": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/$defs/Shade" + } + }, + "outdoor_shades": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/$defs/Shade" + } + }, + "multiplier": { + "type": "integer", + "minimum": 1, + "default": 1 + }, + "exclude_floor_area": { + "type": "boolean", + "default": false + }, + "zone": { + "type": [ + "string", + "null" + ] + }, + "story": { + "type": [ + "string", + "null" + ] + }, + "properties": { + "$ref": "#/$defs/RoomPropertiesAbridged" + } + }, + "required": [ + "type", + "faces", + "properties" + ], + "additionalProperties": false + } + ] + }, + "ModelProperties": { + "type": "object", + "properties": { + "type": { + "const": "ModelProperties" + }, + "energy": { + "type": [ + "object", + "null" + ] + }, + "radiance": { + "type": [ + "object", + "null" + ] + }, + "doe2": { + "type": [ + "object", + "null" + ] + } + }, + "additionalProperties": false + }, + "Model": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "Model" + }, + "version": { + "type": "string", + "pattern": "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$", + "default": "0.0.0" + }, + "rooms": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/$defs/Room" + } + }, + "orphaned_faces": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/$defs/Face" + } + }, + "orphaned_apertures": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/$defs/Aperture" + } + }, + "orphaned_doors": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/$defs/Door" + } + }, + "orphaned_shades": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/$defs/Shade" + } + }, + "shade_meshes": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/$defs/ShadeMesh" + } + }, + "units": { + "$ref": "#/$defs/Units" + }, + "tolerance": { + "type": "number", + "minimum": 0, + "default": 0.01 + }, + "angle_tolerance": { + "type": "number", + "minimum": 0, + "default": 1.0 + }, + "properties": { + "$ref": "#/$defs/ModelProperties" + } + }, + "required": [ + "type", + "properties" + ], + "additionalProperties": false + } + ] } - } -} + }, + "$ref": "#/$defs/Model" +} \ No newline at end of file diff --git a/schema-cfd.json b/schema-cfd.json new file mode 100644 index 0000000..a1ceafa --- /dev/null +++ b/schema-cfd.json @@ -0,0 +1,735 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "bps/cfd", + "title": "CFD Wind Environment Simulation Schema", + "description": "Computational Fluid Dynamics simulation parameters for building wind environment analysis. Covers domain definition, mesh parameters, turbulence models, boundary conditions, and solver settings. Not part of HBJSON; provided as a parallel simulation domain.", + "$defs": { + "_IdentifiedObject": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "pattern": "^[.A-Za-z0-9_-]+$", + "minLength": 1, + "maxLength": 100 + }, + "display_name": { + "type": [ + "string", + "null" + ] + }, + "user_data": { + "type": [ + "object", + "null" + ] + } + }, + "required": [ + "identifier" + ] + }, + "WindProfileType": { + "type": "string", + "enum": [ + "power_law", + "log_law", + "uniform", + "atmospheric_boundary_layer" + ] + }, + "TerrainCategory": { + "type": "string", + "enum": [ + "open_sea", + "open_country", + "suburban", + "urban_center", + "dense_urban" + ] + }, + "TurbulenceModel": { + "type": "string", + "enum": [ + "k_epsilon_standard", + "k_epsilon_realizable", + "k_epsilon_RNG", + "k_omega_SST", + "LES", + "DES" + ] + }, + "SolverType": { + "type": "string", + "enum": [ + "steady", + "transient" + ] + }, + "WindProfile": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "WindProfile" + }, + "profile_type": { + "$ref": "#/$defs/WindProfileType", + "default": "power_law" + }, + "reference_wind_speed": { + "type": "number", + "exclusiveMinimum": 0, + "description": "m/s at reference height" + }, + "reference_height": { + "type": "number", + "exclusiveMinimum": 0, + "default": 10, + "description": "m" + }, + "power_law_exponent": { + "type": "number", + "minimum": 0, + "description": "Alpha for power law profile, terrain-dependent" + }, + "roughness_length": { + "type": "number", + "exclusiveMinimum": 0, + "description": "z0 in meters for log law profile" + }, + "ground_elevation": { + "type": "number", + "default": 0, + "description": "Ground elevation in meters" + }, + "terrain_category": { + "$ref": "#/$defs/TerrainCategory", + "default": "suburban" + }, + "wind_direction": { + "type": "number", + "minimum": 0, + "maximum": 360, + "default": 0, + "description": "Wind direction in degrees, 0=N, 90=E" + } + }, + "required": [ + "type", + "reference_wind_speed" + ], + "additionalProperties": false + } + ] + }, + "CFDDomain": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "CFDDomain" + }, + "domain_size": { + "type": "object", + "properties": { + "x_min": { + "type": "number" + }, + "x_max": { + "type": "number" + }, + "y_min": { + "type": "number" + }, + "y_max": { + "type": "number" + }, + "z_min": { + "type": "number" + }, + "z_max": { + "type": "number" + } + }, + "required": [ + "x_min", + "x_max", + "y_min", + "y_max", + "z_min", + "z_max" + ], + "additionalProperties": false + }, + "upstream_distance": { + "type": "number", + "exclusiveMinimum": 0, + "description": "Distance from building to inlet, typically 5H" + }, + "downstream_distance": { + "type": "number", + "exclusiveMinimum": 0, + "description": "Distance from building to outlet, typically 15H" + }, + "lateral_distance": { + "type": "number", + "exclusiveMinimum": 0, + "description": "Distance from building to side walls, typically 5H" + }, + "height_distance": { + "type": "number", + "exclusiveMinimum": 0, + "description": "Distance from building top to domain top, typically 5H" + } + }, + "required": [ + "type", + "domain_size" + ], + "additionalProperties": false + } + ] + }, + "MeshParameters": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "MeshParameters" + }, + "base_cell_size": { + "type": "number", + "exclusiveMinimum": 0, + "description": "Background mesh cell size in meters" + }, + "refinement_zones": { + "type": "array", + "items": { + "type": "object", + "properties": { + "zone_name": { + "type": "string" + }, + "cell_size": { + "type": "number", + "exclusiveMinimum": 0 + }, + "extent": { + "type": "object", + "properties": { + "x_min": { + "type": "number" + }, + "x_max": { + "type": "number" + }, + "y_min": { + "type": "number" + }, + "y_max": { + "type": "number" + }, + "z_min": { + "type": "number" + }, + "z_max": { + "type": "number" + } + }, + "required": [ + "x_min", + "x_max", + "y_min", + "y_max", + "z_min", + "z_max" + ], + "additionalProperties": false + } + }, + "required": [ + "zone_name", + "cell_size", + "extent" + ], + "additionalProperties": false + } + }, + "wall_layer_first_cell_height": { + "type": "number", + "exclusiveMinimum": 0, + "description": "First cell height at wall boundaries in meters" + }, + "wall_layer_growth_rate": { + "type": "number", + "exclusiveMinimum": 1, + "maximum": 1.5, + "default": 1.2 + }, + "wall_layer_total_layers": { + "type": "integer", + "minimum": 3, + "default": 10 + }, + "mesh_type": { + "type": "string", + "enum": [ + "hexahedral", + "polyhedral", + "tetrahedral", + "snappy_hex" + ], + "default": "snappy_hex" + }, + "total_cells_estimate": { + "type": "integer" + } + }, + "required": [ + "type", + "base_cell_size" + ], + "additionalProperties": false + } + ] + }, + "TurbulenceParameters": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "TurbulenceParameters" + }, + "turbulence_model": { + "$ref": "#/$defs/TurbulenceModel", + "default": "k_epsilon_RNG" + }, + "turbulence_intensity": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Inlet turbulence intensity (0-1)" + }, + "turbulent_length_scale": { + "type": "number", + "exclusiveMinimum": 0, + "description": "Characteristic turbulent length scale in meters" + }, + "wall_function_type": { + "type": "string", + "enum": [ + "standard_wall_function", + "non_equilibrium", + "enhanced_wall_treatment", + "scalable_wall_function" + ], + "default": "standard_wall_function" + }, + "y_plus_target": { + "type": "number", + "exclusiveMinimum": 0, + "description": "Target y+ value for wall-adjacent cells" + } + }, + "required": [ + "type", + "turbulence_model" + ], + "additionalProperties": false + } + ] + }, + "BoundaryConditions": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "BoundaryConditions" + }, + "inlet_type": { + "type": "string", + "enum": [ + "velocity_inlet", + "pressure_inlet" + ], + "default": "velocity_inlet" + }, + "outlet_type": { + "type": "string", + "enum": [ + "pressure_outlet", + "outflow" + ], + "default": "pressure_outlet" + }, + "top_boundary_type": { + "type": "string", + "enum": [ + "symmetry", + "slip_wall", + "velocity_inlet" + ], + "default": "symmetry" + }, + "side_boundary_type": { + "type": "string", + "enum": [ + "symmetry", + "slip_wall" + ], + "default": "symmetry" + }, + "ground_type": { + "type": "string", + "enum": [ + "no_slip_wall", + "rough_wall" + ], + "default": "no_slip_wall" + }, + "building_wall_type": { + "type": "string", + "enum": [ + "no_slip_wall", + "rough_wall" + ], + "default": "no_slip_wall" + }, + "surface_roughness_height": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001, + "description": "Physical roughness height in meters for wall boundaries" + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "SolverSettings": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "SolverSettings" + }, + "solver_type": { + "$ref": "#/$defs/SolverType", + "default": "steady" + }, + "pressure_velocity_coupling": { + "type": "string", + "enum": [ + "SIMPLE", + "SIMPLEC", + "PISO", + "Coupled" + ], + "default": "SIMPLE" + }, + "spatial_discretization": { + "type": "string", + "enum": [ + "first_order", + "second_order", + "QUICK", + "MUSCL" + ], + "default": "second_order" + }, + "max_iterations": { + "type": "integer", + "minimum": 100, + "default": 1000 + }, + "convergence_criteria": { + "type": "object", + "properties": { + "continuity": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + }, + "x_velocity": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + }, + "y_velocity": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + }, + "z_velocity": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + }, + "k": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + }, + "epsilon": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + }, + "omega": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + } + }, + "additionalProperties": false + }, + "under_relaxation_factors": { + "type": "object", + "properties": { + "pressure": { + "type": "number", + "exclusiveMinimum": 0, + "maximum": 1, + "default": 0.3 + }, + "momentum": { + "type": "number", + "exclusiveMinimum": 0, + "maximum": 1, + "default": 0.7 + }, + "turbulent_kinetic_energy": { + "type": "number", + "exclusiveMinimum": 0, + "maximum": 1, + "default": 0.8 + }, + "turbulent_dissipation": { + "type": "number", + "exclusiveMinimum": 0, + "maximum": 1, + "default": 0.8 + } + }, + "additionalProperties": false + }, + "time_step": { + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0, + "description": "Time step in seconds (for transient only)" + }, + "total_time": { + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0, + "description": "Total simulation time in seconds (for transient only)" + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "OutputParameters": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "OutputParameters" + }, + "output_variables": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "velocity", + "pressure", + "turbulent_kinetic_energy", + "turbulent_dissipation", + "wall_shear_stress", + "vorticity" + ] + }, + "default": [ + "velocity", + "pressure" + ] + }, + "monitoring_points": { + "type": "array", + "items": { + "type": "object", + "properties": { + "point_name": { + "type": "string" + }, + "position": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3 + } + }, + "required": [ + "point_name", + "position" + ], + "additionalProperties": false + } + }, + "output_format": { + "type": "string", + "enum": [ + "ensight", + "paraview", + "tecplot", + "csv", + "vtk" + ], + "default": "vtk" + }, + "output_interval": { + "type": "integer", + "minimum": 1, + "default": 100, + "description": "Write output every N iterations" + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "CFDSettings": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "CFDSettings" + }, + "wind_profiles": { + "type": "array", + "items": { + "$ref": "#/$defs/WindProfile" + } + }, + "domain": { + "$ref": "#/$defs/CFDDomain" + }, + "mesh": { + "$ref": "#/$defs/MeshParameters" + }, + "turbulence": { + "$ref": "#/$defs/TurbulenceParameters" + }, + "boundary_conditions": { + "$ref": "#/$defs/BoundaryConditions" + }, + "solver": { + "$ref": "#/$defs/SolverSettings" + }, + "output": { + "$ref": "#/$defs/OutputParameters" + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "ModelCFDProperties": { + "type": "object", + "properties": { + "type": { + "const": "ModelCFDProperties" + }, + "cfd_settings": { + "$ref": "#/$defs/CFDSettings" + }, + "building_surfaces": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of building surface identifiers to be used as wall boundaries" + }, + "terrain_surfaces": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of terrain/ground surface identifiers" + }, + "porous_surfaces": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of surface identifiers treated as porous media (trees, screens)" + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + } +} \ No newline at end of file diff --git a/schema-community-cfd.json b/schema-community-cfd.json new file mode 100644 index 0000000..12cebe7 --- /dev/null +++ b/schema-community-cfd.json @@ -0,0 +1,662 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "bps/community-cfd", + "title": "Community-Scale CFD Wind Environment Schema", + "description": "CFD parameters for community/site wind environment analysis. Covers domain setup, mesh, turbulence, boundary conditions, and solver settings for neighborhood-scale simulations.", + "$defs": { + "_IdentifiedObject": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "pattern": "^[.A-Za-z0-9_-]+$", + "minLength": 1, + "maxLength": 100 + }, + "display_name": { + "type": [ + "string", + "null" + ] + }, + "user_data": { + "type": [ + "object", + "null" + ] + } + }, + "required": [ + "identifier" + ] + }, + "WindProfileType": { + "type": "string", + "enum": [ + "power_law", + "log_law", + "uniform", + "atmospheric_boundary_layer" + ] + }, + "TerrainCategory": { + "type": "string", + "enum": [ + "open_sea", + "open_country", + "suburban", + "urban_center", + "dense_urban" + ] + }, + "TurbulenceModel": { + "type": "string", + "enum": [ + "k_epsilon_standard", + "k_epsilon_realizable", + "k_epsilon_RNG", + "k_omega_SST", + "LES", + "DES" + ] + }, + "SolverType": { + "type": "string", + "enum": [ + "steady", + "transient" + ] + }, + "WindProfile": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "WindProfile" + }, + "profile_type": { + "$ref": "#/$defs/WindProfileType", + "default": "power_law" + }, + "reference_wind_speed": { + "type": "number", + "exclusiveMinimum": 0 + }, + "reference_height": { + "type": "number", + "exclusiveMinimum": 0, + "default": 10 + }, + "power_law_exponent": { + "type": "number", + "minimum": 0 + }, + "roughness_length": { + "type": "number", + "exclusiveMinimum": 0 + }, + "ground_elevation": { + "type": "number", + "default": 0 + }, + "terrain_category": { + "$ref": "#/$defs/TerrainCategory", + "default": "suburban" + }, + "wind_direction": { + "type": "number", + "minimum": 0, + "maximum": 360, + "default": 0 + } + }, + "required": [ + "type", + "reference_wind_speed" + ], + "additionalProperties": false + } + ] + }, + "CFDDomain": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "CFDDomain" + }, + "domain_size": { + "type": "object", + "properties": { + "x_min": { + "type": "number" + }, + "x_max": { + "type": "number" + }, + "y_min": { + "type": "number" + }, + "y_max": { + "type": "number" + }, + "z_min": { + "type": "number" + }, + "z_max": { + "type": "number" + } + }, + "required": [ + "x_min", + "x_max", + "y_min", + "y_max", + "z_min", + "z_max" + ], + "additionalProperties": false + }, + "upstream_distance": { + "type": "number", + "exclusiveMinimum": 0, + "description": "typically 5H" + }, + "downstream_distance": { + "type": "number", + "exclusiveMinimum": 0, + "description": "typically 15H" + }, + "lateral_distance": { + "type": "number", + "exclusiveMinimum": 0, + "description": "typically 5H" + }, + "height_distance": { + "type": "number", + "exclusiveMinimum": 0, + "description": "typically 5H" + } + }, + "required": [ + "type", + "domain_size" + ], + "additionalProperties": false + } + ] + }, + "MeshParameters": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "MeshParameters" + }, + "base_cell_size": { + "type": "number", + "exclusiveMinimum": 0 + }, + "refinement_zones": { + "type": "array", + "items": { + "type": "object", + "properties": { + "zone_name": { + "type": "string" + }, + "cell_size": { + "type": "number", + "exclusiveMinimum": 0 + }, + "extent": { + "type": "object", + "properties": { + "x_min": { + "type": "number" + }, + "x_max": { + "type": "number" + }, + "y_min": { + "type": "number" + }, + "y_max": { + "type": "number" + }, + "z_min": { + "type": "number" + }, + "z_max": { + "type": "number" + } + }, + "required": [ + "x_min", + "x_max", + "y_min", + "y_max", + "z_min", + "z_max" + ], + "additionalProperties": false + } + }, + "required": [ + "zone_name", + "cell_size", + "extent" + ], + "additionalProperties": false + } + }, + "wall_layer_first_cell_height": { + "type": "number", + "exclusiveMinimum": 0 + }, + "wall_layer_growth_rate": { + "type": "number", + "exclusiveMinimum": 1, + "maximum": 1.5, + "default": 1.2 + }, + "wall_layer_total_layers": { + "type": "integer", + "minimum": 3, + "default": 10 + }, + "mesh_type": { + "type": "string", + "enum": [ + "hexahedral", + "polyhedral", + "tetrahedral", + "snappy_hex" + ], + "default": "snappy_hex" + } + }, + "required": [ + "type", + "base_cell_size" + ], + "additionalProperties": false + } + ] + }, + "TurbulenceParameters": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "TurbulenceParameters" + }, + "turbulence_model": { + "$ref": "#/$defs/TurbulenceModel", + "default": "k_epsilon_RNG" + }, + "turbulence_intensity": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "turbulent_length_scale": { + "type": "number", + "exclusiveMinimum": 0 + }, + "wall_function_type": { + "type": "string", + "enum": [ + "standard_wall_function", + "non_equilibrium", + "enhanced_wall_treatment", + "scalable_wall_function" + ], + "default": "standard_wall_function" + }, + "y_plus_target": { + "type": "number", + "exclusiveMinimum": 0 + } + }, + "required": [ + "type", + "turbulence_model" + ], + "additionalProperties": false + } + ] + }, + "BoundaryConditions": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "BoundaryConditions" + }, + "inlet_type": { + "type": "string", + "enum": [ + "velocity_inlet", + "pressure_inlet" + ], + "default": "velocity_inlet" + }, + "outlet_type": { + "type": "string", + "enum": [ + "pressure_outlet", + "outflow" + ], + "default": "pressure_outlet" + }, + "top_boundary_type": { + "type": "string", + "enum": [ + "symmetry", + "slip_wall", + "velocity_inlet" + ], + "default": "symmetry" + }, + "side_boundary_type": { + "type": "string", + "enum": [ + "symmetry", + "slip_wall" + ], + "default": "symmetry" + }, + "ground_type": { + "type": "string", + "enum": [ + "no_slip_wall", + "rough_wall" + ], + "default": "no_slip_wall" + }, + "building_wall_type": { + "type": "string", + "enum": [ + "no_slip_wall", + "rough_wall" + ], + "default": "no_slip_wall" + }, + "surface_roughness_height": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "SolverSettings": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "SolverSettings" + }, + "solver_type": { + "$ref": "#/$defs/SolverType", + "default": "steady" + }, + "pressure_velocity_coupling": { + "type": "string", + "enum": [ + "SIMPLE", + "SIMPLEC", + "PISO", + "Coupled" + ], + "default": "SIMPLE" + }, + "spatial_discretization": { + "type": "string", + "enum": [ + "first_order", + "second_order", + "QUICK", + "MUSCL" + ], + "default": "second_order" + }, + "max_iterations": { + "type": "integer", + "minimum": 100, + "default": 1000 + }, + "convergence_criteria": { + "type": "object", + "properties": { + "continuity": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + }, + "x_velocity": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + }, + "y_velocity": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + }, + "z_velocity": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + }, + "k": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + }, + "epsilon": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + } + }, + "additionalProperties": false + }, + "under_relaxation_factors": { + "type": "object", + "properties": { + "pressure": { + "type": "number", + "exclusiveMinimum": 0, + "maximum": 1, + "default": 0.3 + }, + "momentum": { + "type": "number", + "exclusiveMinimum": 0, + "maximum": 1, + "default": 0.7 + }, + "k": { + "type": "number", + "exclusiveMinimum": 0, + "maximum": 1, + "default": 0.8 + }, + "epsilon": { + "type": "number", + "exclusiveMinimum": 0, + "maximum": 1, + "default": 0.8 + } + }, + "additionalProperties": false + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "OutputParameters": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "OutputParameters" + }, + "output_variables": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "velocity", + "pressure", + "turbulent_kinetic_energy", + "turbulent_dissipation", + "wall_shear_stress", + "vorticity" + ] + }, + "default": [ + "velocity", + "pressure" + ] + }, + "monitoring_points": { + "type": "array", + "items": { + "type": "object", + "properties": { + "point_name": { + "type": "string" + }, + "position": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3 + } + }, + "required": [ + "point_name", + "position" + ], + "additionalProperties": false + } + }, + "output_format": { + "type": "string", + "enum": [ + "ensight", + "paraview", + "tecplot", + "csv", + "vtk" + ], + "default": "vtk" + }, + "output_interval": { + "type": "integer", + "minimum": 1, + "default": 100 + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "CommunityCFDSettings": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "CommunityCFDSettings" + }, + "wind_profiles": { + "type": "array", + "items": { + "$ref": "#/$defs/WindProfile" + } + }, + "domain": { + "$ref": "#/$defs/CFDDomain" + }, + "mesh": { + "$ref": "#/$defs/MeshParameters" + }, + "turbulence": { + "$ref": "#/$defs/TurbulenceParameters" + }, + "boundary_conditions": { + "$ref": "#/$defs/BoundaryConditions" + }, + "solver": { + "$ref": "#/$defs/SolverSettings" + }, + "output": { + "$ref": "#/$defs/OutputParameters" + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + } + } +} \ No newline at end of file diff --git a/schema-community-energy.json b/schema-community-energy.json new file mode 100644 index 0000000..7e0025d --- /dev/null +++ b/schema-community-energy.json @@ -0,0 +1,263 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "bps/community-energy", + "title": "Community-Scale Energy Schema", + "description": "District energy system parameters for community scale. Covers plants, networks, pipes, and building connections.", + "$defs": { + "_IdentifiedObject": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "pattern": "^[.A-Za-z0-9_-]+$", + "minLength": 1, + "maxLength": 100 + }, + "display_name": { + "type": [ + "string", + "null" + ] + }, + "user_data": { + "type": [ + "object", + "null" + ] + } + }, + "required": [ + "identifier" + ] + }, + "PlantType": { + "type": "string", + "enum": [ + "CHP", + "GasBoiler", + "ElectricBoiler", + "GroundSourceHeatPump", + "AirSourceHeatPump", + "Chiller", + "CoolingTower", + "ThermalStorage", + "SolarThermal", + "PV" + ] + }, + "NetworkType": { + "type": "string", + "enum": [ + "CHW", + "HW", + "Steam", + "Electricity" + ] + }, + "Plant": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "Plant" + }, + "plant_type": { + "$ref": "#/$defs/PlantType" + }, + "rated_capacity": { + "type": "number", + "exclusiveMinimum": 0, + "description": "kW" + }, + "cop": { + "type": "number", + "exclusiveMinimum": 0 + }, + "fuel_type": { + "type": "string", + "default": "natural_gas" + }, + "location": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3 + } + }, + "required": [ + "type", + "plant_type", + "rated_capacity" + ], + "additionalProperties": false + } + ] + }, + "Pipe": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "Pipe" + }, + "start_node": { + "type": "string" + }, + "end_node": { + "type": "string" + }, + "length": { + "type": "number", + "exclusiveMinimum": 0, + "description": "m" + }, + "diameter": { + "type": "number", + "exclusiveMinimum": 0, + "description": "m" + }, + "insulation_thickness": { + "type": "number", + "minimum": 0, + "default": 0 + }, + "insulation_conductivity": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.04 + } + }, + "required": [ + "type", + "start_node", + "end_node", + "length", + "diameter" + ], + "additionalProperties": false + } + ] + }, + "Network": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "Network" + }, + "network_type": { + "$ref": "#/$defs/NetworkType" + }, + "supply_temperature": { + "type": "number", + "description": "Celsius" + }, + "return_temperature": { + "type": "number", + "description": "Celsius" + }, + "pipes": { + "type": "array", + "items": { + "$ref": "#/$defs/Pipe" + } + } + }, + "required": [ + "type", + "network_type", + "pipes" + ], + "additionalProperties": false + } + ] + }, + "BuildingConnection": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "BuildingConnection" + }, + "building_ref": { + "type": "string" + }, + "network_ref": { + "type": "string" + }, + "design_flow_rate": { + "type": "number", + "exclusiveMinimum": 0 + } + }, + "required": [ + "type", + "building_ref", + "network_ref" + ], + "additionalProperties": false + } + ] + }, + "DistrictEnergy": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "DistrictEnergy" + }, + "plants": { + "type": "array", + "items": { + "$ref": "#/$defs/Plant" + } + }, + "networks": { + "type": "array", + "items": { + "$ref": "#/$defs/Network" + } + }, + "connections": { + "type": "array", + "items": { + "$ref": "#/$defs/BuildingConnection" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + } + } +} \ No newline at end of file diff --git a/schema-community-microclimate.json b/schema-community-microclimate.json new file mode 100644 index 0000000..0cf73a8 --- /dev/null +++ b/schema-community-microclimate.json @@ -0,0 +1,68 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "bps/community-microclimate", + "title": "Community-Scale Microclimate Schema", + "description": "Microclimate parameters for community scale: urban heat island, wind correction, and surface albedo.", + "$defs": { + "_IdentifiedObject": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "pattern": "^[.A-Za-z0-9_-]+$", + "minLength": 1, + "maxLength": 100 + }, + "display_name": { + "type": [ + "string", + "null" + ] + }, + "user_data": { + "type": [ + "object", + "null" + ] + } + }, + "required": [ + "identifier" + ] + }, + "MicroClimate": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "MicroClimate" + }, + "uhi_intensity": { + "type": "number", + "description": "Urban heat island intensity in degrees Celsius" + }, + "wind_correction_factor": { + "type": "number", + "default": 1 + }, + "albedo": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.2 + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + } + } +} \ No newline at end of file diff --git a/schema-community.json b/schema-community.json new file mode 100644 index 0000000..991bd95 --- /dev/null +++ b/schema-community.json @@ -0,0 +1,321 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "bps/community", + "title": "Community-Scale Geometry Schema", + "description": "Community/site scale geometry: site boundaries, terrain, roads, green spaces, and water bodies. Energy, CFD, and other simulation parameters are in separate schema-community-*.json files.", + "$defs": { + "_IdentifiedObject": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "pattern": "^[.A-Za-z0-9_-]+$", + "minLength": 1, + "maxLength": 100 + }, + "display_name": { + "type": [ + "string", + "null" + ] + }, + "user_data": { + "type": [ + "object", + "null" + ] + } + }, + "required": [ + "identifier" + ] + }, + "TerrainGrid": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "TerrainGrid" + }, + "grid_origin": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3 + }, + "grid_size_x": { + "type": "integer", + "minimum": 1 + }, + "grid_size_y": { + "type": "integer", + "minimum": 1 + }, + "cell_size": { + "type": "number", + "exclusiveMinimum": 0 + }, + "elevations": { + "type": "array", + "items": { + "type": "number" + } + } + }, + "required": [ + "type", + "grid_origin", + "grid_size_x", + "grid_size_y", + "cell_size", + "elevations" + ], + "additionalProperties": false + } + ] + }, + "TerrainTIN": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "TerrainTIN" + }, + "vertices": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3 + }, + "minItems": 3 + }, + "triangles": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "integer", + "minimum": 0 + }, + "minItems": 3, + "maxItems": 3 + }, + "minItems": 1 + } + }, + "required": [ + "type", + "vertices", + "triangles" + ], + "additionalProperties": false + } + ] + }, + "Road": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "Road" + }, + "centerline": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 2, + "maxItems": 3 + }, + "minItems": 2 + }, + "width": { + "type": "number", + "exclusiveMinimum": 0 + }, + "surface_material": { + "type": "string", + "default": "asphalt" + } + }, + "required": [ + "type", + "centerline", + "width" + ], + "additionalProperties": false + } + ] + }, + "GreenSpace": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "GreenSpace" + }, + "boundary": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 2, + "maxItems": 2 + }, + "minItems": 3 + }, + "vegetation_type": { + "type": "string", + "default": "grass" + }, + "leaf_area_index": { + "type": "number", + "minimum": 0, + "default": 1 + } + }, + "required": [ + "type", + "boundary" + ], + "additionalProperties": false + } + ] + }, + "WaterBody": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "WaterBody" + }, + "boundary": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 2, + "maxItems": 2 + }, + "minItems": 3 + }, + "depth": { + "type": "number", + "exclusiveMinimum": 0, + "default": 1 + }, + "water_temperature": { + "type": "number", + "default": 20 + } + }, + "required": [ + "type", + "boundary" + ], + "additionalProperties": false + } + ] + }, + "Site": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "Site" + }, + "boundary": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 2, + "maxItems": 2 + }, + "minItems": 3 + }, + "terrain": { + "oneOf": [ + { + "$ref": "#/$defs/TerrainGrid" + }, + { + "$ref": "#/$defs/TerrainTIN" + }, + { + "type": "null" + } + ] + }, + "roads": { + "type": "array", + "items": { + "$ref": "#/$defs/Road" + } + }, + "green_spaces": { + "type": "array", + "items": { + "$ref": "#/$defs/GreenSpace" + } + }, + "water_bodies": { + "type": "array", + "items": { + "$ref": "#/$defs/WaterBody" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + } + } +} \ No newline at end of file diff --git a/schema-energy.json b/schema-energy.json index baa6ab0..8048d2c 100644 --- a/schema-energy.json +++ b/schema-energy.json @@ -1,201 +1,2713 @@ { - "archgen": { - "version": "0.1.0", - "description": "ArchGen Schema — 能耗模拟领域", - "tags": { - "scale": { - "building": "建筑尺度", - "community": "社区/街区尺度", - "urban": "城市尺度" - }, - "simulation": { - "energy": "能耗模拟", - "daylight": "采光分析", - "solar": "日照分析", - "thermal_comfort": "热舒适分析", - "carbon": "碳排放核算", - "wind": "风环境模拟", - "general": "通用" - } - } - }, - - "types": { - "TimePoint": { - "description": "时刻点 [时, 分]", - "fields": { - "hour": { "type": "integer", "default": 0 }, - "minute": { "type": "integer", "default": 0 } - } - }, - "DatePoint": { - "description": "日期点 [月, 日]", - "fields": { - "month": { "type": "integer", "default": 1 }, - "day": { "type": "integer", "default": 1 } - } - }, - "Period": { - "description": "时间范围", - "fields": { - "start": { "type": "DatePoint" }, - "end": { "type": "DatePoint" } - } - } - }, - - "enums": { - "MaterialType": { - "description": "材料类型", - "values": ["EnergyMaterial", "EnergyMaterialNoMass", "EnergyWindowMaterialSimpleGlazSys"] - }, - "ConstructionType": { - "description": "构造类型", - "values": ["OpaqueConstruction", "WindowConstruction"] - }, + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "bps/energy", + "title": "HBJSON Energy Simulation Schema", + "description": "EnergyPlus simulation parameters compatible with honeybee-schema energy properties. Covers materials, constructions, schedules, program types, and HVAC.", + "$defs": { "Roughness": { - "description": "表面粗糙度", - "values": ["VeryRough", "Rough", "MediumRough", "MediumSmooth", "Smooth", "VerySmooth"] - } - }, - - "entities": { - "MaterialProps": { - "description": "材料热工物理属性", - "tags": { "scale": ["building", "community"], "simulation": ["energy", "thermal_comfort", "carbon"] }, - "attributes": { - "identifier": { "type": "string", "required": true, "tags": { "simulation": ["general"] } }, - "displayName": { "type": "string", "tags": { "simulation": ["general"] } }, - "type": { "type": "MaterialType", "default": "EnergyMaterial", "tags": { "simulation": ["energy", "carbon"] } }, - "conductivity": { "type": "number", "default": 1, "unit": "W/m·K", "description": "导热系数", "tags": { "simulation": ["energy", "thermal_comfort"] } }, - "specificHeat": { "type": "number", "default": 100, "unit": "J/kg·K", "description": "热容", "tags": { "simulation": ["energy", "thermal_comfort"] } }, - "density": { "type": "number", "default": 1000, "unit": "kg/m³", "description": "密度", "tags": { "simulation": ["energy", "carbon"] } }, - "thickness": { "type": "number", "default": 100, "unit": "mm", "description": "厚度", "tags": { "simulation": ["energy", "thermal_comfort", "carbon"] } }, - "roughness": { "type": "Roughness", "default": "MediumRough", "description": "表面粗糙度", "tags": { "simulation": ["energy", "thermal_comfort"] } }, - "thermalAbsorptance": { "type": "number", "default": 0.9, "description": "热吸收率", "tags": { "scale": ["building"], "simulation": ["energy", "thermal_comfort"] } }, - "solarAbsorptance": { "type": "number", "default": 0.9, "description": "太阳吸收率", "tags": { "simulation": ["energy", "daylight", "solar", "thermal_comfort"] } }, - "visibleAbsorptance": { "type": "number", "default": 0.9, "description": "可见光吸收率", "tags": { "scale": ["building"], "simulation": ["daylight"] } }, - "rValue": { "type": "number", "unit": "m²·K/W", "description": "热阻", "tags": { "simulation": ["energy", "thermal_comfort"] } }, - "uFactor": { "type": "number", "unit": "W/m²·K", "description": "传热系数", "tags": { "simulation": ["energy", "thermal_comfort"] } }, - "shgc": { "type": "number", "default": 0.6, "description": "太阳得热系数", "tags": { "simulation": ["energy", "daylight", "solar", "thermal_comfort"] } }, - "vt": { "type": "number", "default": 0.6, "description": "可见光透射比", "tags": { "simulation": ["daylight"] } }, - "embodiedCarbon": { "type": "number", "default": 0, "unit": "kgCO₂/m²", "description": "隐含碳排放", "tags": { "scale": ["building", "community", "urban"], "simulation": ["carbon"] } }, - "embodiedEnergy": { "type": "number", "default": 0, "unit": "MJ/m²", "description": "隐含能耗", "tags": { "scale": ["building", "community", "urban"], "simulation": ["carbon"] } } - } + "type": "string", + "enum": [ + "VeryRough", + "Rough", + "MediumRough", + "MediumSmooth", + "Smooth", + "VerySmooth" + ] }, - - "Construction": { - "description": "单一构造定义(包含多层材料)", - "tags": { "scale": ["building"], "simulation": ["energy", "thermal_comfort", "carbon"] }, - "attributes": { - "identifier": { "type": "string", "required": true, "tags": { "simulation": ["general"] } }, - "displayName": { "type": "string", "required": true, "tags": { "simulation": ["general"] } }, - "type": { "type": "ConstructionType", "default": "OpaqueConstruction", "tags": { "simulation": ["energy", "thermal_comfort", "carbon"] } } + "GasType": { + "type": "string", + "enum": [ + "Air", + "Argon", + "Krypton", + "Xenon", + "Custom" + ] + }, + "ShadeType": { + "type": "string", + "enum": [ + "VenetianHorizontal", + "VenetianVertical", + "VenetianRotated", + "Mesh", + "Perforated", + "Screen", + "Blind" + ] + }, + "BlindControlType": { + "type": "string", + "enum": [ + "AlwaysOff", + "AlwaysOn", + "Schedule", + "OnIfHighSolarOnWindow", + "OnIfHighHorizontalSolar", + "OnIfHighOutdoorDryBulbTemperature", + "OnIfHighOutdoorWetBulbTemperature", + "OffIfHighOutdoorDryBulbTemperature", + "OffIfHighOutdoorWetBulbTemperature" + ] + }, + "_IdentifiedObject": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "pattern": "^[.A-Za-z0-9_-]+$", + "minLength": 1, + "maxLength": 100 + }, + "display_name": { + "type": [ + "string", + "null" + ] + }, + "user_data": { + "type": [ + "object", + "null" + ] + } }, - "children": { - "materials": { "type": "MaterialProps", "multiple": true, "description": "材料层列表(从外到内)", "tags": { "simulation": ["energy", "thermal_comfort", "carbon"] } } - } + "required": [ + "identifier" + ] }, - - "SubSet": { - "description": "特定部位的构造组合", - "tags": { "scale": ["building"], "simulation": ["energy", "thermal_comfort", "carbon"] }, - "attributes": { - "identifier": { "type": "string", "required": true, "tags": { "simulation": ["general"] } }, - "type": { "type": "string", "tags": { "simulation": ["general"] } }, - "exteriorConstruction": { "type": "Construction", "description": "外部构造", "tags": { "simulation": ["energy", "thermal_comfort", "carbon"] } }, - "interiorConstruction": { "type": "Construction", "description": "内部构造", "tags": { "simulation": ["energy", "thermal_comfort"] } }, - "groundConstruction": { "type": "Construction", "description": "地面构造", "tags": { "simulation": ["energy", "thermal_comfort"] } }, - "overheadConstruction": { "type": "Construction", "description": "顶棚构造", "tags": { "simulation": ["energy", "thermal_comfort"] } }, - "skylightConstruction": { "type": "Construction", "description": "天窗构造", "tags": { "simulation": ["energy", "daylight"] } }, - "operableConstruction": { "type": "Construction", "description": "可开启构造", "tags": { "simulation": ["energy", "wind"] } }, - "windowConstruction": { "type": "Construction", "description": "窗户构造", "tags": { "simulation": ["energy", "daylight", "solar"] } } - } + "EnergyMaterial": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "EnergyMaterial" + }, + "roughness": { + "$ref": "#/$defs/Roughness", + "default": "MediumRough" + }, + "thickness": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.1 + }, + "conductivity": { + "type": "number", + "exclusiveMinimum": 0, + "default": 1 + }, + "density": { + "type": "number", + "exclusiveMinimum": 0, + "default": 1000 + }, + "specific_heat": { + "type": "number", + "exclusiveMinimum": 0, + "default": 1000 + }, + "thermal_absorptance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.9 + }, + "solar_absorptance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.7 + }, + "visible_absorptance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.7 + } + }, + "required": [ + "type", + "thickness", + "conductivity", + "density", + "specific_heat" + ], + "additionalProperties": false + } + ] }, - - "ConstructionSet": { - "description": "全楼构造合集", - "tags": { "scale": ["building"], "simulation": ["energy", "thermal_comfort", "carbon"] }, - "attributes": { - "identifier": { "type": "string", "required": true, "tags": { "simulation": ["general"] } }, - "displayName": { "type": "string", "required": true, "tags": { "simulation": ["general"] } }, - "airBoundaryConstruction": { "type": "string", "description": "空气边界构造 ID", "tags": { "simulation": ["energy"] } }, - "shadeConstruction": { "type": "string", "description": "遮阳构造 ID", "tags": { "simulation": ["energy", "daylight", "solar"] } } - }, - "children": { - "wallSet": { "type": "SubSet", "description": "墙体构造", "tags": { "simulation": ["energy", "thermal_comfort", "carbon"] } }, - "floorSet": { "type": "SubSet", "description": "楼板构造", "tags": { "simulation": ["energy", "thermal_comfort", "carbon"] } }, - "roofCeilingSet": { "type": "SubSet", "description": "屋顶/顶棚构造", "tags": { "simulation": ["energy", "thermal_comfort", "carbon"] } }, - "doorSet": { "type": "SubSet", "description": "门构造", "tags": { "simulation": ["energy", "thermal_comfort"] } }, - "apertureSet": { "type": "SubSet", "description": "洞口构造", "tags": { "simulation": ["energy", "daylight", "solar"] } } - } + "EnergyMaterialNoMass": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "EnergyMaterialNoMass" + }, + "roughness": { + "$ref": "#/$defs/Roughness", + "default": "MediumRough" + }, + "thermal_resistance": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.1 + }, + "thermal_absorptance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.9 + }, + "solar_absorptance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.7 + }, + "visible_absorptance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.7 + } + }, + "required": [ + "type", + "thermal_resistance" + ], + "additionalProperties": false + } + ] }, - - "RoomProgram": { - "description": "房间功能程序定义(人员、灯光、设备等热增益参数)", - "tags": { "scale": ["building"], "simulation": ["energy", "thermal_comfort", "carbon"] }, - "attributes": { - "identifier": { "type": "string", "required": true, "tags": { "simulation": ["general"] } }, - "displayName": { "type": "string", "required": true, "tags": { "simulation": ["general"] } }, - "peopleDensity": { "type": "number", "default": 0.0333, "unit": "people/m²", "description": "人员密度", "tags": { "simulation": ["energy", "thermal_comfort", "carbon"] } }, - "lightingDensity": { "type": "number", "default": 0, "unit": "W/m²", "description": "照明功率密度", "tags": { "simulation": ["energy", "daylight", "carbon"] } }, - "equipmentDensity": { "type": "number", "default": 0, "unit": "W/m²", "description": "设备功率密度", "tags": { "simulation": ["energy", "carbon"] } }, - "infiltrationCoefficient": { "type": "number", "default": 0.0003, "unit": "m³/s·m²", "description": "渗透风系数", "tags": { "simulation": ["energy", "wind", "thermal_comfort"] } }, - "heatingSetpoint": { "type": "number", "default": 18, "unit": "°C", "description": "采暖设定温度", "tags": { "simulation": ["energy", "thermal_comfort"] } }, - "coolingSetpoint": { "type": "number", "default": 26, "unit": "°C", "description": "制冷设定温度", "tags": { "simulation": ["energy", "thermal_comfort"] } } - }, - "children": { - "occupancySchedule": { "type": "ScheduleRuleset", "description": "人员在室率排程", "tags": { "simulation": ["energy", "thermal_comfort"] } }, - "lightingSchedule": { "type": "ScheduleRuleset", "description": "照明使用率排程", "tags": { "simulation": ["energy", "daylight"] } }, - "equipmentSchedule": { "type": "ScheduleRuleset", "description": "设备使用率排程", "tags": { "simulation": ["energy"] } }, - "infiltrationSchedule": { "type": "ScheduleRuleset", "description": "渗透风排程", "tags": { "simulation": ["energy", "wind"] } }, - "heatingSchedule": { "type": "ScheduleRuleset", "description": "采暖设定温度排程", "tags": { "simulation": ["energy", "thermal_comfort"] } }, - "coolingSchedule": { "type": "ScheduleRuleset", "description": "制冷设定温度排程", "tags": { "simulation": ["energy", "thermal_comfort"] } } - } + "EnergyMaterialVegetation": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "EnergyMaterialVegetation" + }, + "roughness": { + "$ref": "#/$defs/Roughness", + "default": "MediumRough" + }, + "thickness": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.1 + }, + "conductivity": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.1 + }, + "density": { + "type": "number", + "exclusiveMinimum": 0, + "default": 100 + }, + "specific_heat": { + "type": "number", + "exclusiveMinimum": 0, + "default": 1400 + }, + "leaf_area_index": { + "type": "number", + "minimum": 0, + "default": 1 + }, + "leaf_reflectivity": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.2 + }, + "leaf_emissivity": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.9 + }, + "min_stomatal_resistance": { + "type": "number", + "minimum": 0, + "default": 180 + }, + "soil_layer_name": { + "type": [ + "string", + "null" + ] + }, + "thermal_absorptance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.9 + } + }, + "required": [ + "type", + "thickness", + "conductivity", + "density", + "specific_heat", + "leaf_area_index" + ], + "additionalProperties": false + } + ] + }, + "EnergyWindowMaterialGlazing": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "EnergyWindowMaterialGlazing" + }, + "solar_transmittance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.7 + }, + "solar_transmittance_normal_incidence": { + "type": [ + "number", + "null" + ] + }, + "solar_reflectance_front": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.07 + }, + "solar_reflectance_back": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.07 + }, + "visible_transmittance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.9 + }, + "visible_transmittance_normal_incidence": { + "type": [ + "number", + "null" + ] + }, + "visible_reflectance_front": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.07 + }, + "visible_reflectance_back": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.07 + }, + "infrared_transmittance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "infrared_hemisissivity_front": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.84 + }, + "infrared_hemisissivity_back": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.84 + }, + "thickness": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.006 + }, + "conductivity": { + "type": "number", + "exclusiveMinimum": 0, + "default": 1 + }, + "dirt_correction_factor": { + "type": "number", + "minimum": 0.8, + "maximum": 1, + "default": 1 + }, + "solar_diffusing": { + "type": "boolean", + "default": false + } + }, + "required": [ + "type", + "thickness" + ], + "additionalProperties": false + } + ] + }, + "EnergyWindowMaterialGas": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "EnergyWindowMaterialGas" + }, + "gas_type": { + "$ref": "#/$defs/GasType", + "default": "Air" + }, + "thickness": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.0127 + } + }, + "required": [ + "type", + "thickness" + ], + "additionalProperties": false + } + ] + }, + "EnergyWindowMaterialGasCustom": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "EnergyWindowMaterialGasCustom" + }, + "conductivity_coefficient_A": { + "type": "number", + "default": 0 + }, + "conductivity_coefficient_B": { + "type": "number", + "default": 0 + }, + "viscosity_coefficient_A": { + "type": "number", + "default": 0 + }, + "viscosity_coefficient_B": { + "type": "number", + "default": 0 + }, + "specific_heat_coefficient_A": { + "type": "number", + "default": 0 + }, + "specific_heat_coefficient_B": { + "type": "number", + "default": 0 + }, + "specific_heat_ratio": { + "type": "number", + "default": 0 + }, + "molecular_weight": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0 + }, + "thickness": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.0127 + } + }, + "required": [ + "type", + "thickness" + ], + "additionalProperties": false + } + ] + }, + "EnergyWindowMaterialGasMixture": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "EnergyWindowMaterialGasMixture" + }, + "gas_key_options": { + "type": "array", + "items": { + "$ref": "#/$defs/GasType" + }, + "minItems": 2, + "maxItems": 10 + }, + "gas_fractions": { + "type": "array", + "items": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "minItems": 2, + "maxItems": 10 + }, + "thickness": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.0127 + } + }, + "required": [ + "type", + "gas_key_options", + "gas_fractions", + "thickness" + ], + "additionalProperties": false + } + ] + }, + "EnergyWindowMaterialSimpleGlazSys": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "EnergyWindowMaterialSimpleGlazSys" + }, + "u_factor": { + "type": "number", + "exclusiveMinimum": 0, + "default": 1 + }, + "shgc": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.6 + }, + "visible_transmittance": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "maximum": 1 + } + }, + "required": [ + "type", + "u_factor", + "shgc" + ], + "additionalProperties": false + } + ] + }, + "EnergyWindowMaterialBlind": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "EnergyWindowMaterialBlind" + }, + "shade_type": { + "$ref": "#/$defs/ShadeType", + "default": "VenetianHorizontal" + }, + "slat_material": { + "type": "string", + "default": "Aluminum" + }, + "slat_width": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.025 + }, + "slat_separation": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.021 + }, + "slat_thickness": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.0005 + }, + "slat_angle": { + "type": "number", + "minimum": -90, + "maximum": 90, + "default": 45 + }, + "slat_conductivity": { + "type": "number", + "exclusiveMinimum": 0, + "default": 177 + }, + "slat_beam_solar_transmittance": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "maximum": 1 + }, + "slat_beam_solar_reflectance": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "maximum": 1 + }, + "slat_diffuse_solar_transmittance": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "maximum": 1 + }, + "slat_diffuse_solar_reflectance": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "maximum": 1 + }, + "slat_beam_visible_transmittance": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "maximum": 1 + }, + "slat_beam_visible_reflectance": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "maximum": 1 + }, + "slat_diffuse_visible_transmittance": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "maximum": 1 + }, + "slat_diffuse_visible_reflectance": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "maximum": 1 + }, + "slat_infrared_transmittance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "slat_infrared_hemisissivity_front": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.9 + }, + "slat_infrared_hemisissivity_back": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.9 + }, + "slat_infrared_hemisissivity_holes": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.9 + }, + "slat_conductivity_ratio": { + "type": "number", + "exclusiveMinimum": 0, + "default": 1 + }, + "top_opening_multiplier": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "bottom_opening_multiplier": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "side_opening_multiplier": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + } + }, + "required": [ + "type", + "slat_width", + "slat_separation", + "slat_thickness", + "slat_angle" + ], + "additionalProperties": false + } + ] + }, + "EnergyWindowMaterialShade": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "EnergyWindowMaterialShade" + }, + "shade_type": { + "$ref": "#/$defs/ShadeType", + "default": "Mesh" + }, + "solar_transmittance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.3 + }, + "solar_reflectance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.5 + }, + "visible_transmittance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.3 + }, + "visible_reflectance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.5 + }, + "infrared_hemisissivity": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.9 + }, + "infrared_transmittance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "thickness": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + }, + "conductivity": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.1 + } + }, + "required": [ + "type", + "thickness", + "conductivity" + ], + "additionalProperties": false + } + ] + }, + "EnergyWindowFrame": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "EnergyWindowFrame" + }, + "frame_conductance": { + "type": "number", + "exclusiveMinimum": 0, + "default": 1 + }, + "frame_edge_glazing_correction_factor": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.85 + }, + "frame_area": { + "type": "number", + "exclusiveMinimum": 0 + }, + "inside_sill_depth": { + "type": "number", + "default": 0.0254 + }, + "inside_sill_insulation_ratio": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.6 + }, + "outside_sill_depth": { + "type": "number", + "default": 0.0254 + }, + "outside_sill_insulation_ratio": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.6 + }, + "absorptance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.5 + } + }, + "required": [ + "type", + "frame_conductance", + "frame_area" + ], + "additionalProperties": false + } + ] + }, + "OpaqueConstruction": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "OpaqueConstruction" + }, + "layers": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/$defs/EnergyMaterial" + }, + { + "$ref": "#/$defs/EnergyMaterialNoMass" + }, + { + "$ref": "#/$defs/EnergyMaterialVegetation" + } + ] + }, + "minItems": 1 + } + }, + "required": [ + "type", + "layers" + ], + "additionalProperties": false + } + ] + }, + "WindowConstruction": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "WindowConstruction" + }, + "layers": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/$defs/EnergyWindowMaterialSimpleGlazSys" + }, + { + "$ref": "#/$defs/EnergyWindowMaterialGlazing" + }, + { + "$ref": "#/$defs/EnergyWindowMaterialGas" + }, + { + "$ref": "#/$defs/EnergyWindowMaterialGasCustom" + }, + { + "$ref": "#/$defs/EnergyWindowMaterialGasMixture" + } + ] + }, + "minItems": 1 + } + }, + "required": [ + "type", + "layers" + ], + "additionalProperties": false + } + ] + }, + "WindowConstructionShade": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "WindowConstructionShade" + }, + "window_construction": { + "oneOf": [ + { + "$ref": "#/$defs/WindowConstruction" + }, + { + "$ref": "#/$defs/EnergyWindowMaterialSimpleGlazSys" + } + ] + }, + "indoor_shade": { + "oneOf": [ + { + "$ref": "#/$defs/EnergyWindowMaterialBlind" + }, + { + "$ref": "#/$defs/EnergyWindowMaterialShade" + } + ] + }, + "outdoor_shade": { + "oneOf": [ + { + "$ref": "#/$defs/EnergyWindowMaterialBlind" + }, + { + "$ref": "#/$defs/EnergyWindowMaterialShade" + } + ] + }, + "blind_control_type": { + "$ref": "#/$defs/BlindControlType", + "default": "AlwaysOff" + }, + "blind_schedule": { + "type": [ + "string", + "null" + ] + }, + "slat_angle_schedule": { + "type": [ + "string", + "null" + ] + }, + "outdoor_blind_schedule": { + "type": [ + "string", + "null" + ] + }, + "outdoor_slat_angle_schedule": { + "type": [ + "string", + "null" + ] + }, + "switchable_glazing_schedule": { + "type": [ + "string", + "null" + ] + }, + "outdoor_blind_control_type": { + "$ref": "#/$defs/BlindControlType", + "default": "AlwaysOff" + } + }, + "required": [ + "type", + "window_construction" + ], + "additionalProperties": false + } + ] + }, + "WindowConstructionDynamic": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "WindowConstructionDynamic" + }, + "window_constructions": { + "type": "array", + "items": { + "$ref": "#/$defs/WindowConstruction" + }, + "minItems": 2 + } + }, + "required": [ + "type", + "window_constructions" + ], + "additionalProperties": false + } + ] + }, + "AirBoundaryConstruction": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "AirBoundaryConstruction" + }, + "mixing_per_room_floor_area": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.00372 + }, + "mixing_air_flow_coefficient": { + "type": "number", + "exclusiveMinimum": 0, + "default": 1 + }, + "thermal_resistance": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.05 + } + }, + "required": [ + "type", + "mixing_per_room_floor_area", + "mixing_air_flow_coefficient" + ], + "additionalProperties": false + } + ] + }, + "ShadeConstruction": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "ShadeConstruction" + }, + "solar_reflectance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.2 + }, + "visible_reflectance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.2 + }, + "is_specular": { + "type": "boolean", + "default": false + }, + "transmittance_schedule": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "OpaqueConstructionAbridged": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "OpaqueConstructionAbridged" + }, + "layers": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1 + } + }, + "required": [ + "type", + "layers" + ], + "additionalProperties": false + } + ] + }, + "WindowConstructionAbridged": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "WindowConstructionAbridged" + }, + "layers": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1 + } + }, + "required": [ + "type", + "layers" + ], + "additionalProperties": false + } + ] + }, + "AirBoundaryConstructionAbridged": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "AirBoundaryConstructionAbridged" + }, + "mixing_per_room_floor_area": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.00372 + }, + "mixing_air_flow_coefficient": { + "type": "number", + "exclusiveMinimum": 0, + "default": 1 + }, + "thermal_resistance": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.05 + } + }, + "required": [ + "type", + "mixing_per_room_floor_area", + "mixing_air_flow_coefficient" + ], + "additionalProperties": false + } + ] + }, + "ScheduleTypeLimit": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "ScheduleTypeLimit" + }, + "data_type": { + "type": "string", + "default": "Continuous" + }, + "unit_type": { + "type": "string", + "default": "Dimensionless" + }, + "lower_limit": { + "type": [ + "number", + "null" + ] + }, + "upper_limit": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] }, - "ScheduleDay": { - "description": "单一全天时刻值序列定义", - "tags": { "simulation": ["general"] }, - "attributes": { - "identifier": { "type": "string", "required": true, "tags": { "simulation": ["general"] } }, - "times": { "type": "TimePoint[]", "description": "时刻点列表", "tags": { "simulation": ["general"] } }, - "values": { "type": "number[]", "description": "对应时刻的值列表", "tags": { "simulation": ["general"] } }, - "interpolate": { "type": "boolean", "default": false, "description": "是否插值", "tags": { "simulation": ["general"] } } - } + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "ScheduleDay" + }, + "values": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 1 + }, + "times": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "integer", + "minimum": 0 + }, + "minItems": 2, + "maxItems": 2 + }, + "minItems": 1 + }, + "interpolate": { + "type": "boolean", + "default": false + } + }, + "required": [ + "type", + "values", + "times" + ], + "additionalProperties": false + } + ] + }, + "ScheduleFixedInterval": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "ScheduleFixedInterval" + }, + "schedule_type_limit": { + "$ref": "#/$defs/ScheduleTypeLimit" + }, + "timestep": { + "type": "integer", + "minimum": 1, + "default": 1 + }, + "values": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 1 + }, + "interpolate": { + "type": "boolean", + "default": false + } + }, + "required": [ + "type", + "values" + ], + "additionalProperties": false + } + ] + }, + "ScheduleRulesetAbridged": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "ScheduleRulesetAbridged" + }, + "schedule_type_limit": { + "oneOf": [ + { + "$ref": "#/$defs/ScheduleTypeLimit" + }, + { + "type": "string" + } + ] + }, + "default_day_schedule_id": { + "type": "string" + }, + "day_schedules": { + "type": "array", + "items": { + "$ref": "#/$defs/ScheduleDay" + }, + "minItems": 1 + }, + "schedule_rules": { + "type": "array", + "items": { + "$ref": "#/$defs/ScheduleRule" + } + }, + "holiday_schedule_id": { + "type": [ + "string", + "null" + ] + }, + "summer_design_day_schedule_id": { + "type": [ + "string", + "null" + ] + }, + "winter_design_day_schedule_id": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type", + "default_day_schedule_id", + "day_schedules" + ], + "additionalProperties": false + } + ] }, - "ScheduleRule": { - "description": "基于日期范围与星期的排程应用规则", - "tags": { "simulation": ["general"] }, - "attributes": { - "startDate": { "type": "DatePoint", "required": true, "description": "规则开始日期", "tags": { "simulation": ["general"] } }, - "endDate": { "type": "DatePoint", "required": true, "description": "规则结束日期", "tags": { "simulation": ["general"] } }, - "applyMonday": { "type": "boolean", "default": true, "tags": { "simulation": ["general"] } }, - "applyTuesday": { "type": "boolean", "default": true, "tags": { "simulation": ["general"] } }, - "applyWednesday": { "type": "boolean", "default": true, "tags": { "simulation": ["general"] } }, - "applyThursday": { "type": "boolean", "default": true, "tags": { "simulation": ["general"] } }, - "applyFriday": { "type": "boolean", "default": true, "tags": { "simulation": ["general"] } }, - "applySaturday": { "type": "boolean", "default": true, "tags": { "simulation": ["general"] } }, - "applySunday": { "type": "boolean", "default": true, "tags": { "simulation": ["general"] } } + "type": "object", + "properties": { + "type": { + "const": "ScheduleRule" + }, + "start_date": { + "type": "array", + "items": { + "type": "integer", + "minimum": 1 + }, + "minItems": 2, + "maxItems": 2 + }, + "end_date": { + "type": "array", + "items": { + "type": "integer", + "minimum": 1 + }, + "minItems": 2, + "maxItems": 2 + }, + "apply_monday": { + "type": "boolean", + "default": true + }, + "apply_tuesday": { + "type": "boolean", + "default": true + }, + "apply_wednesday": { + "type": "boolean", + "default": true + }, + "apply_thursday": { + "type": "boolean", + "default": true + }, + "apply_friday": { + "type": "boolean", + "default": true + }, + "apply_saturday": { + "type": "boolean", + "default": true + }, + "apply_sunday": { + "type": "boolean", + "default": true + }, + "day_schedule_id": { + "type": "string" + } }, - "children": { - "scheduleDay": { "type": "ScheduleDay", "description": "关联的日排程", "tags": { "simulation": ["general"] } } - } + "required": [ + "type", + "day_schedule_id" + ], + "additionalProperties": false }, - - "ScheduleRuleset": { - "description": "排程规则集(包含默认值与特殊规则)", - "tags": { "simulation": ["general"] }, - "attributes": { - "identifier": { "type": "string", "required": true, "tags": { "simulation": ["general"] } }, - "displayName": { "type": "string", "tags": { "simulation": ["general"] } } + "PeopleAbridged": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "PeopleAbridged" + }, + "people_per_square_meter": { + "type": "number", + "default": 0 + }, + "occupancy_schedule": { + "type": [ + "string", + "null" + ] + }, + "activity_schedule": { + "type": [ + "string", + "null" + ] + }, + "latent_fraction_schedule": { + "type": [ + "string", + "null" + ] + }, + "radiant_fraction": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.3 + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "LightingAbridged": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "LightingAbridged" + }, + "watts_per_square_meter": { + "type": "number", + "default": 0 + }, + "lighting_schedule": { + "type": [ + "string", + "null" + ] + }, + "visible_fraction": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.2 + }, + "radiant_fraction": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.7 + }, + "return_air_fraction": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "ElectricEquipmentAbridged": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "ElectricEquipmentAbridged" + }, + "watts_per_square_meter": { + "type": "number", + "default": 0 + }, + "equipment_schedule": { + "type": [ + "string", + "null" + ] + }, + "radiant_fraction": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.5 + }, + "latent_fraction": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "lost_fraction": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "GasEquipmentAbridged": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "GasEquipmentAbridged" + }, + "watts_per_square_meter": { + "type": "number", + "default": 0 + }, + "equipment_schedule": { + "type": [ + "string", + "null" + ] + }, + "radiant_fraction": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.1 + }, + "latent_fraction": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.1 + }, + "lost_fraction": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.4 + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "ServiceHotWaterAbridged": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "ServiceHotWaterAbridged" + }, + "liters_per_hour_per_person": { + "type": "number", + "default": 0 + }, + "hot_water_schedule": { + "type": [ + "string", + "null" + ] + }, + "hot_water_target_temperature": { + "type": "number", + "default": 60 + }, + "cold_water_temperature": { + "type": "number", + "default": 10 + }, + "hot_water_fraction": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.6 + }, + "waste_water_fraction": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "InfiltrationAbridged": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "InfiltrationAbridged" + }, + "air_changes_per_hour": { + "type": "number", + "default": 0 + }, + "infiltration_schedule": { + "type": [ + "string", + "null" + ] + }, + "constant_coefficient": { + "type": "number", + "default": 1 + }, + "temperature_coefficient": { + "type": "number", + "default": 0 + }, + "velocity_coefficient": { + "type": "number", + "default": 0 + }, + "temperature_difference_type": { + "type": [ + "string", + "null" + ] + }, + "velocity_type": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "VentilationAbridged": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "VentilationAbridged" + }, + "outdoor_air_per_person": { + "type": "number", + "default": 0 + }, + "outdoor_air_per_area": { + "type": "number", + "default": 0 + }, + "air_changes_per_hour": { + "type": "number", + "default": 0 + }, + "sum_per_floor_area": { + "type": "number", + "default": 0 + }, + "ventilation_schedule": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "SetpointAbridged": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "SetpointAbridged" + }, + "heating_schedule": { + "type": [ + "string", + "null" + ] + }, + "cooling_schedule": { + "type": [ + "string", + "null" + ] + }, + "humidifying_schedule": { + "type": [ + "string", + "null" + ] + }, + "dehumidifying_schedule": { + "type": [ + "string", + "null" + ] + }, + "minimum_input_ratio_heating_schedule": { + "type": [ + "string", + "null" + ] + }, + "minimum_input_ratio_cooling_schedule": { + "type": [ + "string", + "null" + ] + }, + "maximum_dry_bulb_temperature_setpoint": { + "type": "number", + "default": 300 + }, + "minimum_dry_bulb_temperature_setpoint": { + "type": "number", + "default": 0 + }, + "delta_temperature": { + "type": "number", + "default": 0 + }, + "delta_temperature_setpoint_type": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "InternalMassAbridged": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "InternalMassAbridged" + }, + "construction": { + "type": [ + "string", + "null" + ] + }, + "surface_area_per_floor_area": { + "type": "number", + "default": 0 + }, + "surface_area": { + "type": [ + "number", + "null" + ] + }, + "number_of_units": { + "type": "number", + "default": 0 + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "DaylightingControl": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "DaylightingControl" + }, + "illuminance_setpoint": { + "type": "number", + "default": 0 + }, + "lighting_control_type": { + "type": "integer", + "minimum": 0, + "maximum": 4, + "default": 1 + }, + "glare_sensor_azimuth": { + "type": "number", + "default": 0 + }, + "minimum_input_power_fraction": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.3 + }, + "minimum_light_output_fraction": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.2 + }, + "setpoint_at_reference_point_1": { + "type": [ + "number", + "null" + ] + }, + "setpoint_at_reference_point_2": { + "type": [ + "number", + "null" + ] + }, + "sensor_position_1": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3 + }, + "sensor_position_2": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3 + }, + "de daylighting_schedule": { + "type": [ + "string", + "null" + ] + }, + "availability_schedule": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "VentilationOpening": { + "type": "object", + "properties": { + "type": { + "const": "VentilationOpening" + }, + "operable_fraction": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 1 + }, + "discharge_coefficient": { + "type": "number", + "default": 0.65 + }, + "discharge_coefficient_when_no_wind": { + "type": "number", + "default": 0.65 + }, + "opening_factor": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 1 + } }, - "children": { - "defaultDaySchedule": { "type": "ScheduleDay", "description": "默认日排程", "tags": { "simulation": ["general"] } }, - "scheduleRules": { "type": "ScheduleRule", "multiple": true, "description": "特殊规则列表", "tags": { "simulation": ["general"] } }, - "daySchedules": { "type": "ScheduleDay", "multiple": true, "description": "所有日排程列表", "tags": { "simulation": ["general"] } } - } + "required": [ + "type" + ], + "additionalProperties": false + }, + "ProgramTypeAbridged": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "ProgramTypeAbridged" + }, + "people": { + "oneOf": [ + { + "$ref": "#/$defs/PeopleAbridged" + }, + { + "type": "string" + } + ] + }, + "lighting": { + "oneOf": [ + { + "$ref": "#/$defs/LightingAbridged" + }, + { + "type": "string" + } + ] + }, + "electric_equipment": { + "oneOf": [ + { + "$ref": "#/$defs/ElectricEquipmentAbridged" + }, + { + "type": "string" + } + ] + }, + "gas_equipment": { + "oneOf": [ + { + "$ref": "#/$defs/GasEquipmentAbridged" + }, + { + "type": "string" + } + ] + }, + "service_hot_water": { + "oneOf": [ + { + "$ref": "#/$defs/ServiceHotWaterAbridged" + }, + { + "type": "string" + } + ] + }, + "infiltration": { + "oneOf": [ + { + "$ref": "#/$defs/InfiltrationAbridged" + }, + { + "type": "string" + } + ] + }, + "ventilation": { + "oneOf": [ + { + "$ref": "#/$defs/VentilationAbridged" + }, + { + "type": "string" + } + ] + }, + "setpoint": { + "oneOf": [ + { + "$ref": "#/$defs/SetpointAbridged" + }, + { + "type": "string" + } + ] + }, + "internal_mass": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/$defs/InternalMassAbridged" + }, + { + "type": "string" + } + ] + } + }, + "daylighting_control": { + "$ref": "#/$defs/DaylightingControl" + }, + "comfort_parameters": { + "type": [ + "object", + "null" + ] + }, + "process": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/$defs/ProcessAbridged" + }, + { + "type": "string" + } + ] + } + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "ProcessAbridged": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "ProcessAbridged" + }, + "watts_per_square_meter": { + "type": "number", + "default": 0 + }, + "process_schedule": { + "type": [ + "string", + "null" + ] + }, + "radiant_fraction": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.5 + }, + "latent_fraction": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "lost_fraction": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "IdealAirSystemAbridged": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "IdealAirSystemAbridged" + }, + "system_air_flow_rate": { + "type": "string", + "default": "Autosize" + }, + "demand_controlled_ventilation_type": { + "type": [ + "string", + "null" + ] + }, + "demand_high_altitude_cooling": { + "type": "boolean", + "default": false + }, + "heat_recovery_type": { + "type": [ + "string", + "null" + ] + }, + "sensible_heat_recovery": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "latent_heat_recovery": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "economizer_type": { + "type": [ + "string", + "null" + ] + }, + "economizer_maximum_dry_bulb_temperature": { + "type": [ + "number", + "null" + ] + }, + "economizer_maximum_enthalpy": { + "type": [ + "number", + "null" + ] + }, + "cooling_limit": { + "type": "number" + }, + "cooling_air_temperature": { + "type": [ + "number", + "null" + ] + }, + "heating_limit": { + "type": "number" + }, + "heating_air_temperature": { + "type": [ + "number", + "null" + ] + }, + "outdoor_air_mixer_type": { + "type": [ + "string", + "null" + ] + }, + "ventilation_control_type": { + "type": [ + "string", + "null" + ] + }, + "maximum_outdoor_air_flow_rate": { + "type": [ + "string", + "null" + ] + }, + "minimum_outdoor_air_flow_rate": { + "type": [ + "string", + "null" + ] + }, + "humidifier_type": { + "type": [ + "string", + "null" + ] + }, + "dehumidifier_type": { + "type": [ + "string", + "null" + ] + }, + "dehumidification_setpoint": { + "type": [ + "number", + "null" + ] + }, + "cooling_setpoint": { + "type": [ + "string", + "null" + ] + }, + "heating_setpoint": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "ConstructionSetAbridged": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "ConstructionSetAbridged" + }, + "wall_construction": { + "type": [ + "string", + "null" + ] + }, + "floor_construction": { + "type": [ + "string", + "null" + ] + }, + "roof_ceiling_construction": { + "type": [ + "string", + "null" + ] + }, + "aperture_construction": { + "type": [ + "string", + "null" + ] + }, + "door_construction": { + "type": [ + "string", + "null" + ] + }, + "skylight_construction": { + "type": [ + "string", + "null" + ] + }, + "interior_wall_construction": { + "type": [ + "string", + "null" + ] + }, + "interior_floor_construction": { + "type": [ + "string", + "null" + ] + }, + "interior_ceiling_construction": { + "type": [ + "string", + "null" + ] + }, + "ground_wall_construction": { + "type": [ + "string", + "null" + ] + }, + "ground_floor_construction": { + "type": [ + "string", + "null" + ] + }, + "ground_ceiling_construction": { + "type": [ + "string", + "null" + ] + }, + "air_boundary_construction": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "BuildingType": { + "type": "string", + "enum": [ + "Residential", + "SingleFamily", + "MultiFamily", + "Office", + "Retail", + "PrimarySchool", + "SecondarySchool", + "Hospital", + "College", + "Warehouse", + "HotelSmall", + "HotelLarge", + "Restaurant", + "OutPatientHealthCare", + "InPatientHealthCare" + ] + }, + "DefaultProgramTypesAbridged": { + "type": "object", + "properties": { + "type": { + "const": "DefaultProgramTypesAbridged" + }, + "program_type": { + "type": "object", + "patternProperties": { + ".*": { + "oneOf": [ + { + "$ref": "#/$defs/ProgramTypeAbridged" + }, + { + "type": "string" + } + ] + } + } + }, + "building_type": { + "$ref": "#/$defs/BuildingType" + } + }, + "required": [ + "type", + "program_type" + ], + "additionalProperties": false + }, + "DefaultConstructionSetAbridged": { + "type": "object", + "properties": { + "type": { + "const": "DefaultConstructionSetAbridged" + }, + "construction_set": { + "oneOf": [ + { + "$ref": "#/$defs/ConstructionSetAbridged" + }, + { + "type": "string" + } + ] + }, + "building_type": { + "$ref": "#/$defs/BuildingType" + } + }, + "required": [ + "type", + "construction_set" + ], + "additionalProperties": false + }, + "ModelEnergyProperties": { + "type": "object", + "properties": { + "type": { + "const": "ModelEnergyProperties" + }, + "construction_sets": { + "type": "array", + "items": { + "$ref": "#/$defs/ConstructionSetAbridged" + } + }, + "materials": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/$defs/EnergyMaterial" + }, + { + "$ref": "#/$defs/EnergyMaterialNoMass" + }, + { + "$ref": "#/$defs/EnergyMaterialVegetation" + }, + { + "$ref": "#/$defs/EnergyWindowMaterialSimpleGlazSys" + }, + { + "$ref": "#/$defs/EnergyWindowMaterialGlazing" + }, + { + "$ref": "#/$defs/EnergyWindowMaterialGas" + }, + { + "$ref": "#/$defs/EnergyWindowMaterialGasCustom" + }, + { + "$ref": "#/$defs/EnergyWindowMaterialGasMixture" + }, + { + "$ref": "#/$defs/EnergyWindowMaterialBlind" + }, + { + "$ref": "#/$defs/EnergyWindowMaterialShade" + }, + { + "$ref": "#/$defs/EnergyWindowFrame" + } + ] + } + }, + "constructions": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/$defs/OpaqueConstructionAbridged" + }, + { + "$ref": "#/$defs/WindowConstructionAbridged" + }, + { + "$ref": "#/$defs/AirBoundaryConstructionAbridged" + }, + { + "$ref": "#/$defs/ShadeConstruction" + } + ] + } + }, + "schedules": { + "type": "array", + "items": { + "$ref": "#/$defs/ScheduleRulesetAbridged" + } + }, + "schedule_type_limits": { + "type": "array", + "items": { + "$ref": "#/$defs/ScheduleTypeLimit" + } + }, + "program_types": { + "type": "array", + "items": { + "$ref": "#/$defs/ProgramTypeAbridged" + } + }, + "hvac": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/$defs/IdealAirSystemAbridged" + } + ] + } + }, + "shw": { + "type": "array", + "items": { + "type": "object" + } + }, + "default_program_types": { + "$ref": "#/$defs/DefaultProgramTypesAbridged" + }, + "default_construction_sets": { + "$ref": "#/$defs/DefaultConstructionSetAbridged" + }, + "climate_base": { + "type": [ + "object", + "null" + ] + }, + "simulation_control": { + "type": [ + "object", + "null" + ] + }, + "shadow_calculation": { + "type": [ + "object", + "null" + ] + }, + "output_conventions": { + "type": [ + "object", + "null" + ] + }, + "output_meters": { + "type": [ + "array", + "null" + ] + }, + "design_days": { + "type": [ + "array", + "null" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false } } -} +} \ No newline at end of file diff --git a/schema-radiance.json b/schema-radiance.json new file mode 100644 index 0000000..43981f6 --- /dev/null +++ b/schema-radiance.json @@ -0,0 +1,980 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "bps/radiance", + "title": "HBJSON Radiance Daylighting Schema", + "description": "Radiance daylighting simulation parameters compatible with honeybee-schema radiance properties. Covers modifiers, modifier sets, sensor grids, views, and dynamic states.", + "$defs": { + "_IdentifiedObject": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "pattern": "^[.A-Za-z0-9_-]+$", + "minLength": 1, + "maxLength": 100 + }, + "display_name": { + "type": [ + "string", + "null" + ] + }, + "user_data": { + "type": [ + "object", + "null" + ] + } + }, + "required": [ + "identifier" + ] + }, + "Void": { + "type": "object", + "properties": { + "type": { + "const": "Void" + } + }, + "required": [ + "type" + ], + "additionalProperties": false + }, + "Plastic": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "Plastic" + }, + "r_reflectance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "g_reflectance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "b_reflectance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "specularity": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "roughness": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "Metal": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "Metal" + }, + "r_reflectance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "g_reflectance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "b_reflectance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "specularity": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0.9 + }, + "roughness": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "Trans": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "Trans" + }, + "r_reflectance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "g_reflectance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "b_reflectance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "specularity": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "roughness": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "transmitted_diff": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "transmitted_spec": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "Glass": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "Glass" + }, + "r_transmissivity": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "g_transmissivity": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "b_transmissivity": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "refraction_index": { + "type": "number", + "exclusiveMinimum": 1, + "default": 1.52 + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "Mirror": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "Mirror" + }, + "r_reflectance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 1 + }, + "g_reflectance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 1 + }, + "b_reflectance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 1 + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "Light": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "Light" + }, + "r_emittance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "g_emittance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "b_emittance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "Glow": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "Glow" + }, + "r_emittance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "g_emittance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "b_emittance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "default": 0 + }, + "max_radius": { + "type": "number", + "default": 0 + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "BSDF": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "BSDF" + }, + "up_orientation": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3, + "default": [ + 0.01, + 0.01, + 1.0 + ] + }, + "thickness": { + "type": "number", + "default": 0 + }, + "function_file": { + "type": "string", + "minLength": 1, + "maxLength": 100, + "default": "." + }, + "transform": { + "type": [ + "string", + "null" + ], + "minLength": 1, + "maxLength": 100 + }, + "bsdf_data": { + "type": "string", + "minLength": 1 + }, + "front_diffuse_reflectance": { + "type": [ + "array", + "null" + ], + "items": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "minItems": 3, + "maxItems": 3 + }, + "back_diffuse_reflectance": { + "type": [ + "array", + "null" + ], + "items": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "minItems": 3, + "maxItems": 3 + }, + "diffuse_transmittance": { + "type": [ + "array", + "null" + ], + "items": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "minItems": 3, + "maxItems": 3 + } + }, + "required": [ + "type", + "bsdf_data" + ], + "additionalProperties": false + } + ] + }, + "Modifier": { + "oneOf": [ + { + "$ref": "#/$defs/Plastic" + }, + { + "$ref": "#/$defs/Metal" + }, + { + "$ref": "#/$defs/Trans" + }, + { + "$ref": "#/$defs/Glass" + }, + { + "$ref": "#/$defs/Mirror" + }, + { + "$ref": "#/$defs/Light" + }, + { + "$ref": "#/$defs/Glow" + }, + { + "$ref": "#/$defs/BSDF" + }, + { + "$ref": "#/$defs/Void" + } + ] + }, + "WallModifierSetAbridged": { + "type": "object", + "properties": { + "type": { + "const": "WallModifierSetAbridged" + }, + "exterior_modifier": { + "type": [ + "string", + "null" + ] + }, + "interior_modifier": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false + }, + "FloorModifierSetAbridged": { + "type": "object", + "properties": { + "type": { + "const": "FloorModifierSetAbridged" + }, + "exterior_modifier": { + "type": [ + "string", + "null" + ] + }, + "interior_modifier": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false + }, + "RoofCeilingModifierSetAbridged": { + "type": "object", + "properties": { + "type": { + "const": "RoofCeilingModifierSetAbridged" + }, + "exterior_modifier": { + "type": [ + "string", + "null" + ] + }, + "interior_modifier": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false + }, + "ApertureModifierSetAbridged": { + "type": "object", + "properties": { + "type": { + "const": "ApertureModifierSetAbridged" + }, + "window_modifier": { + "type": [ + "string", + "null" + ] + }, + "interior_modifier": { + "type": [ + "string", + "null" + ] + }, + "skylight_modifier": { + "type": [ + "string", + "null" + ] + }, + "operable_modifier": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false + }, + "DoorModifierSetAbridged": { + "type": "object", + "properties": { + "type": { + "const": "DoorModifierSetAbridged" + }, + "exterior_modifier": { + "type": [ + "string", + "null" + ] + }, + "interior_modifier": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false + }, + "ShadeModifierSetAbridged": { + "type": "object", + "properties": { + "type": { + "const": "ShadeModifierSetAbridged" + }, + "exterior_modifier": { + "type": [ + "string", + "null" + ] + }, + "interior_modifier": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false + }, + "ModifierSet": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "ModifierSet" + }, + "wall_set": { + "$ref": "#/$defs/WallModifierSetAbridged" + }, + "floor_set": { + "$ref": "#/$defs/FloorModifierSetAbridged" + }, + "roof_ceiling_set": { + "$ref": "#/$defs/RoofCeilingModifierSetAbridged" + }, + "aperture_set": { + "$ref": "#/$defs/ApertureModifierSetAbridged" + }, + "door_set": { + "$ref": "#/$defs/DoorModifierSetAbridged" + }, + "shade_set": { + "$ref": "#/$defs/ShadeModifierSetAbridged" + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "RadianceSubFaceStateAbridged": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "RadianceSubFaceStateAbridged" + }, + "aperture_modifier": { + "type": [ + "string", + "null" + ] + }, + "door_modifier": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "RadianceShadeStateAbridged": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "RadianceShadeStateAbridged" + }, + "shade_modifier": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "Sensor": { + "type": "object", + "properties": { + "type": { + "const": "Sensor" + }, + "pos": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3 + }, + "dir": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3 + } + }, + "required": [ + "type", + "pos", + "dir" + ], + "additionalProperties": false + }, + "SensorGrid": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "SensorGrid" + }, + "sensors": { + "type": "array", + "items": { + "$ref": "#/$defs/Sensor" + }, + "minItems": 1 + }, + "mesh": { + "type": "object" + }, + "base_geometry": { + "type": "array", + "items": { + "type": "object" + } + }, + "group_identifier": { + "type": [ + "string", + "null" + ] + }, + "room_identifier": { + "type": [ + "string", + "null" + ] + }, + "light_path": { + "type": [ + "array", + "null" + ], + "items": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "required": [ + "type", + "sensors" + ], + "additionalProperties": false + } + ] + }, + "ViewType": { + "type": "string", + "enum": [ + "v", + "h", + "l", + "c", + "a", + "s" + ] + }, + "View": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "View" + }, + "position": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3 + }, + "direction": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3 + }, + "up_vector": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3 + }, + "view_type": { + "$ref": "#/$defs/ViewType", + "default": "v" + }, + "h_size": { + "type": "number", + "default": 60 + }, + "v_size": { + "type": "number", + "default": 60 + }, + "shift": { + "type": [ + "number", + "null" + ] + }, + "lift": { + "type": [ + "number", + "null" + ] + }, + "fore_clip": { + "type": [ + "number", + "null" + ] + }, + "aft_clip": { + "type": [ + "number", + "null" + ] + }, + "group_identifier": { + "type": [ + "string", + "null" + ] + }, + "room_identifier": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type", + "position", + "direction", + "up_vector" + ], + "additionalProperties": false + } + ] + }, + "ModelRadianceProperties": { + "type": "object", + "properties": { + "type": { + "const": "ModelRadianceProperties" + }, + "modifiers": { + "type": "array", + "items": { + "$ref": "#/$defs/Modifier" + } + }, + "modifier_sets": { + "type": "array", + "items": { + "$ref": "#/$defs/ModifierSet" + } + }, + "sensor_grids": { + "type": "array", + "items": { + "$ref": "#/$defs/SensorGrid" + } + }, + "views": { + "type": "array", + "items": { + "$ref": "#/$defs/View" + } + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + } +} \ No newline at end of file diff --git a/schema-urban-cfd.json b/schema-urban-cfd.json new file mode 100644 index 0000000..c5abd12 --- /dev/null +++ b/schema-urban-cfd.json @@ -0,0 +1,741 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "bps/urban-cfd", + "title": "Urban-Scale CFD Wind Environment Schema", + "description": "CFD parameters for urban-scale wind environment analysis. Covers larger domains with multiple districts, street canyon effects, pedestrian-level wind comfort assessment.", + "$defs": { + "_IdentifiedObject": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "pattern": "^[.A-Za-z0-9_-]+$", + "minLength": 1, + "maxLength": 100 + }, + "display_name": { + "type": [ + "string", + "null" + ] + }, + "user_data": { + "type": [ + "object", + "null" + ] + } + }, + "required": [ + "identifier" + ] + }, + "WindProfileType": { + "type": "string", + "enum": [ + "power_law", + "log_law", + "uniform", + "atmospheric_boundary_layer" + ] + }, + "TerrainCategory": { + "type": "string", + "enum": [ + "open_sea", + "open_country", + "suburban", + "urban_center", + "dense_urban" + ] + }, + "TurbulenceModel": { + "type": "string", + "enum": [ + "k_epsilon_standard", + "k_epsilon_realizable", + "k_epsilon_RNG", + "k_omega_SST", + "LES", + "DES" + ] + }, + "SolverType": { + "type": "string", + "enum": [ + "steady", + "transient" + ] + }, + "WindComfortCriteria": { + "type": "string", + "enum": [ + "Laws", + "Davenport", + "NEN_8100", + "COST_732" + ] + }, + "WindProfile": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "WindProfile" + }, + "profile_type": { + "$ref": "#/$defs/WindProfileType", + "default": "power_law" + }, + "reference_wind_speed": { + "type": "number", + "exclusiveMinimum": 0 + }, + "reference_height": { + "type": "number", + "exclusiveMinimum": 0, + "default": 10 + }, + "power_law_exponent": { + "type": "number", + "minimum": 0 + }, + "roughness_length": { + "type": "number", + "exclusiveMinimum": 0 + }, + "ground_elevation": { + "type": "number", + "default": 0 + }, + "terrain_category": { + "$ref": "#/$defs/TerrainCategory", + "default": "suburban" + }, + "wind_direction": { + "type": "number", + "minimum": 0, + "maximum": 360, + "default": 0 + } + }, + "required": [ + "type", + "reference_wind_speed" + ], + "additionalProperties": false + } + ] + }, + "CFDDomain": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "CFDDomain" + }, + "domain_size": { + "type": "object", + "properties": { + "x_min": { + "type": "number" + }, + "x_max": { + "type": "number" + }, + "y_min": { + "type": "number" + }, + "y_max": { + "type": "number" + }, + "z_min": { + "type": "number" + }, + "z_max": { + "type": "number" + } + }, + "required": [ + "x_min", + "x_max", + "y_min", + "y_max", + "z_min", + "z_max" + ], + "additionalProperties": false + }, + "upstream_distance": { + "type": "number", + "exclusiveMinimum": 0, + "description": "typically 5H" + }, + "downstream_distance": { + "type": "number", + "exclusiveMinimum": 0, + "description": "typically 15H" + }, + "lateral_distance": { + "type": "number", + "exclusiveMinimum": 0, + "description": "typically 5H" + }, + "height_distance": { + "type": "number", + "exclusiveMinimum": 0, + "description": "typically 5H" + } + }, + "required": [ + "type", + "domain_size" + ], + "additionalProperties": false + } + ] + }, + "MeshParameters": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "MeshParameters" + }, + "base_cell_size": { + "type": "number", + "exclusiveMinimum": 0 + }, + "refinement_zones": { + "type": "array", + "items": { + "type": "object", + "properties": { + "zone_name": { + "type": "string" + }, + "cell_size": { + "type": "number", + "exclusiveMinimum": 0 + }, + "extent": { + "type": "object", + "properties": { + "x_min": { + "type": "number" + }, + "x_max": { + "type": "number" + }, + "y_min": { + "type": "number" + }, + "y_max": { + "type": "number" + }, + "z_min": { + "type": "number" + }, + "z_max": { + "type": "number" + } + }, + "required": [ + "x_min", + "x_max", + "y_min", + "y_max", + "z_min", + "z_max" + ], + "additionalProperties": false + } + }, + "required": [ + "zone_name", + "cell_size", + "extent" + ], + "additionalProperties": false + } + }, + "pedestrian_level_height": { + "type": "number", + "minimum": 0, + "maximum": 3, + "default": 1.5, + "description": "m, height for pedestrian wind assessment" + }, + "pedestrian_cell_size": { + "type": "number", + "exclusiveMinimum": 0, + "default": 1.0, + "description": "m, fine mesh at pedestrian level" + }, + "wall_layer_first_cell_height": { + "type": "number", + "exclusiveMinimum": 0 + }, + "wall_layer_growth_rate": { + "type": "number", + "exclusiveMinimum": 1, + "maximum": 1.5, + "default": 1.2 + }, + "wall_layer_total_layers": { + "type": "integer", + "minimum": 3, + "default": 10 + }, + "mesh_type": { + "type": "string", + "enum": [ + "hexahedral", + "polyhedral", + "tetrahedral", + "snappy_hex" + ], + "default": "snappy_hex" + } + }, + "required": [ + "type", + "base_cell_size" + ], + "additionalProperties": false + } + ] + }, + "TurbulenceParameters": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "TurbulenceParameters" + }, + "turbulence_model": { + "$ref": "#/$defs/TurbulenceModel", + "default": "k_epsilon_RNG" + }, + "turbulence_intensity": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "turbulent_length_scale": { + "type": "number", + "exclusiveMinimum": 0 + }, + "wall_function_type": { + "type": "string", + "enum": [ + "standard_wall_function", + "non_equilibrium", + "enhanced_wall_treatment", + "scalable_wall_function" + ], + "default": "standard_wall_function" + }, + "y_plus_target": { + "type": "number", + "exclusiveMinimum": 0 + } + }, + "required": [ + "type", + "turbulence_model" + ], + "additionalProperties": false + } + ] + }, + "BoundaryConditions": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "BoundaryConditions" + }, + "inlet_type": { + "type": "string", + "enum": [ + "velocity_inlet", + "pressure_inlet" + ], + "default": "velocity_inlet" + }, + "outlet_type": { + "type": "string", + "enum": [ + "pressure_outlet", + "outflow" + ], + "default": "pressure_outlet" + }, + "top_boundary_type": { + "type": "string", + "enum": [ + "symmetry", + "slip_wall", + "velocity_inlet" + ], + "default": "symmetry" + }, + "side_boundary_type": { + "type": "string", + "enum": [ + "symmetry", + "slip_wall" + ], + "default": "symmetry" + }, + "ground_type": { + "type": "string", + "enum": [ + "no_slip_wall", + "rough_wall" + ], + "default": "no_slip_wall" + }, + "building_wall_type": { + "type": "string", + "enum": [ + "no_slip_wall", + "rough_wall" + ], + "default": "no_slip_wall" + }, + "surface_roughness_height": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "SolverSettings": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "SolverSettings" + }, + "solver_type": { + "$ref": "#/$defs/SolverType", + "default": "steady" + }, + "pressure_velocity_coupling": { + "type": "string", + "enum": [ + "SIMPLE", + "SIMPLEC", + "PISO", + "Coupled" + ], + "default": "SIMPLE" + }, + "spatial_discretization": { + "type": "string", + "enum": [ + "first_order", + "second_order", + "QUICK", + "MUSCL" + ], + "default": "second_order" + }, + "max_iterations": { + "type": "integer", + "minimum": 100, + "default": 1000 + }, + "convergence_criteria": { + "type": "object", + "properties": { + "continuity": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + }, + "x_velocity": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + }, + "y_velocity": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + }, + "z_velocity": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + }, + "k": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + }, + "epsilon": { + "type": "number", + "exclusiveMinimum": 0, + "default": 0.001 + } + }, + "additionalProperties": false + }, + "under_relaxation_factors": { + "type": "object", + "properties": { + "pressure": { + "type": "number", + "exclusiveMinimum": 0, + "maximum": 1, + "default": 0.3 + }, + "momentum": { + "type": "number", + "exclusiveMinimum": 0, + "maximum": 1, + "default": 0.7 + }, + "k": { + "type": "number", + "exclusiveMinimum": 0, + "maximum": 1, + "default": 0.8 + }, + "epsilon": { + "type": "number", + "exclusiveMinimum": 0, + "maximum": 1, + "default": 0.8 + } + }, + "additionalProperties": false + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "WindComfortAssessment": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "WindComfortAssessment" + }, + "criteria": { + "$ref": "#/$defs/WindComfortCriteria", + "default": "NEN_8100" + }, + "pedestrian_level_height": { + "type": "number", + "minimum": 0, + "maximum": 3, + "default": 1.5 + }, + "evaluation_points": { + "type": "array", + "items": { + "type": "object", + "properties": { + "point_name": { + "type": "string" + }, + "position": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3 + } + }, + "required": [ + "point_name", + "position" + ], + "additionalProperties": false + } + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "OutputParameters": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "OutputParameters" + }, + "output_variables": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "velocity", + "pressure", + "turbulent_kinetic_energy", + "turbulent_dissipation", + "wall_shear_stress", + "vorticity" + ] + }, + "default": [ + "velocity", + "pressure" + ] + }, + "monitoring_points": { + "type": "array", + "items": { + "type": "object", + "properties": { + "point_name": { + "type": "string" + }, + "position": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3 + } + }, + "required": [ + "point_name", + "position" + ], + "additionalProperties": false + } + }, + "output_format": { + "type": "string", + "enum": [ + "ensight", + "paraview", + "tecplot", + "csv", + "vtk" + ], + "default": "vtk" + }, + "output_interval": { + "type": "integer", + "minimum": 1, + "default": 100 + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "UrbanCFDSettings": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "UrbanCFDSettings" + }, + "wind_profiles": { + "type": "array", + "items": { + "$ref": "#/$defs/WindProfile" + } + }, + "domain": { + "$ref": "#/$defs/CFDDomain" + }, + "mesh": { + "$ref": "#/$defs/MeshParameters" + }, + "turbulence": { + "$ref": "#/$defs/TurbulenceParameters" + }, + "boundary_conditions": { + "$ref": "#/$defs/BoundaryConditions" + }, + "solver": { + "$ref": "#/$defs/SolverSettings" + }, + "wind_comfort": { + "$ref": "#/$defs/WindComfortAssessment" + }, + "output": { + "$ref": "#/$defs/OutputParameters" + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + } + } +} \ No newline at end of file diff --git a/schema-urban-energy.json b/schema-urban-energy.json new file mode 100644 index 0000000..191b1f3 --- /dev/null +++ b/schema-urban-energy.json @@ -0,0 +1,234 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "bps/urban-energy", + "title": "Urban-Scale Energy Schema", + "description": "Urban scale energy parameters: aggregate energy demand, renewable energy potential, and city-level energy systems.", + "$defs": { + "_IdentifiedObject": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "pattern": "^[.A-Za-z0-9_-]+$", + "minLength": 1, + "maxLength": 100 + }, + "display_name": { + "type": [ + "string", + "null" + ] + }, + "user_data": { + "type": [ + "object", + "null" + ] + } + }, + "required": [ + "identifier" + ] + }, + "UrbanEnergyDemand": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "UrbanEnergyDemand" + }, + "land_use_ref": { + "type": "string", + "description": "Reference to LandUse identifier" + }, + "annual_heating_demand": { + "type": "number", + "minimum": 0, + "description": "kWh per year" + }, + "annual_cooling_demand": { + "type": "number", + "minimum": 0, + "description": "kWh per year" + }, + "annual_lighting_demand": { + "type": "number", + "minimum": 0, + "description": "kWh per year" + }, + "annual_equipment_demand": { + "type": "number", + "minimum": 0, + "description": "kWh per year" + }, + "peak_heating_demand": { + "type": "number", + "minimum": 0, + "description": "kW" + }, + "peak_cooling_demand": { + "type": "number", + "minimum": 0, + "description": "kW" + }, + "demand_density": { + "type": "number", + "minimum": 0, + "description": "kWh per square meter per year" + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "RenewablePotential": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "RenewablePotential" + }, + "land_use_ref": { + "type": "string" + }, + "solar_roof_potential": { + "type": "number", + "minimum": 0, + "description": "kWh per year from rooftop PV" + }, + "solar_facade_potential": { + "type": "number", + "minimum": 0, + "description": "kWh per year from facade BIPV" + }, + "solar_ground_potential": { + "type": "number", + "minimum": 0, + "description": "kWh per year from ground-mounted PV" + }, + "geothermal_potential": { + "type": "number", + "minimum": 0, + "description": "kWh per year from ground source" + }, + "wind_potential": { + "type": "number", + "minimum": 0, + "description": "kWh per year from small wind turbines" + }, + "available_roof_area": { + "type": "number", + "minimum": 0, + "description": "square meters suitable for PV" + }, + "suitable_facade_area": { + "type": "number", + "minimum": 0, + "description": "square meters suitable for BIPV" + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "UrbanEnergyBalance": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "UrbanEnergyBalance" + }, + "annual_total_demand": { + "type": "number", + "minimum": 0, + "description": "kWh per year" + }, + "annual_total_renewable_generation": { + "type": "number", + "minimum": 0, + "description": "kWh per year" + }, + "renewable_self_sufficiency_ratio": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "annual_co2_emissions": { + "type": "number", + "description": "tonnes CO2 per year" + }, + "carbon_intensity": { + "type": "number", + "description": "kg CO2 per kWh" + }, + "energy_use_intensity": { + "type": "number", + "minimum": 0, + "description": "kWh per square meter per year" + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "UrbanEnergyProperties": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "UrbanEnergyProperties" + }, + "demands": { + "type": "array", + "items": { + "$ref": "#/$defs/UrbanEnergyDemand" + } + }, + "renewable_potentials": { + "type": "array", + "items": { + "$ref": "#/$defs/RenewablePotential" + } + }, + "energy_balance": { + "$ref": "#/$defs/UrbanEnergyBalance" + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + } + } +} \ No newline at end of file diff --git a/schema-urban.json b/schema-urban.json new file mode 100644 index 0000000..4fda4aa --- /dev/null +++ b/schema-urban.json @@ -0,0 +1,148 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "bps/urban", + "title": "Urban-Scale Geometry Schema", + "description": "Urban scale geometry: climate zones and land use boundaries. Energy, CFD, and other simulation parameters are in separate schema-urban-*.json files.", + "$defs": { + "_IdentifiedObject": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "pattern": "^[.A-Za-z0-9_-]+$", + "minLength": 1, + "maxLength": 100 + }, + "display_name": { + "type": [ + "string", + "null" + ] + }, + "user_data": { + "type": [ + "object", + "null" + ] + } + }, + "required": [ + "identifier" + ] + }, + "ClimateZone": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "ClimateZone" + }, + "boundary": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 2, + "maxItems": 2 + }, + "minItems": 3 + }, + "climate_zone_code": { + "type": "string", + "description": "e.g. ASHRAE (1A-8B), Chinese (\u4e25\u5bd2/\u5bd2\u51b7/\u590f\u70ed\u51ac\u51b7/\u590f\u70ed\u51ac\u6696/\u6e29\u548c)" + }, + "heating_degree_days": { + "type": "number" + }, + "cooling_degree_days": { + "type": "number" + }, + "design_heating_temperature": { + "type": "number" + }, + "design_cooling_temperature": { + "type": "number" + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + ] + }, + "LandUse": { + "type": "object", + "allOf": [ + { + "$ref": "#/$defs/_IdentifiedObject" + }, + { + "type": "object", + "properties": { + "type": { + "const": "LandUse" + }, + "boundary": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "number" + }, + "minItems": 2, + "maxItems": 2 + }, + "minItems": 3 + }, + "land_use_type": { + "type": "string", + "enum": [ + "residential", + "commercial", + "industrial", + "institutional", + "agricultural", + "park", + "water", + "transportation", + "mixed" + ] + }, + "floor_area_ratio": { + "type": "number", + "minimum": 0 + }, + "building_coverage_ratio": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "green_ratio": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "population_density": { + "type": "number", + "minimum": 0, + "description": "people per hectare" + } + }, + "required": [ + "type", + "land_use_type" + ], + "additionalProperties": false + } + ] + } + } +} \ No newline at end of file