From 3697e16547a44f50e071f8bafbc6012498cd69e2 Mon Sep 17 00:00:00 2001 From: Alexandre CUER Date: Wed, 1 Jul 2026 22:42:50 +0200 Subject: [PATCH 1/3] correct north_axis in yaml examples for agence_ACF --- conf/a2w_hp.yml | 5 +++-- conf/a2w_hp_w_gas_backup_oat_control.yml | 3 ++- conf/borehole_500ml_3loops_RAW_GAZBCKP.yml | 17 +++++++---------- conf/borehole_500ml_tubes.yml | 7 ++++--- conf/borehole_500ml_tubes_w_gas_backup.yml | 8 +++++--- conf/gaz_heater.yml | 3 ++- configuration.yml | 5 +++-- 7 files changed, 26 insertions(+), 22 deletions(-) diff --git a/conf/a2w_hp.yml b/conf/a2w_hp.yml index 21b1225..f4b9a6e 100644 --- a/conf/a2w_hp.yml +++ b/conf/a2w_hp.yml @@ -1,4 +1,5 @@ -building_name: batiment_600m2 +building_name: Agence_ACF +North_Axis: 122.4 name: air2water_hp_35KW suffix: single_loop @@ -36,7 +37,7 @@ water_law_set_point: hpatw_eir: force_side: Load_Side - Reference_Capacity : 35000 + #Reference_Capacity : 47000 Reference_Coefficient_Of_Performance: 3.2 # x = water temp / y = air temp capacity_c: 0.794900878202383 diff --git a/conf/a2w_hp_w_gas_backup_oat_control.yml b/conf/a2w_hp_w_gas_backup_oat_control.yml index ac8e23a..6042d0f 100644 --- a/conf/a2w_hp_w_gas_backup_oat_control.yml +++ b/conf/a2w_hp_w_gas_backup_oat_control.yml @@ -1,4 +1,5 @@ -building_name: batiment_600m2 +building_name: Agence_ACF +North_Axis: 122.4 verbose: diff --git a/conf/borehole_500ml_3loops_RAW_GAZBCKP.yml b/conf/borehole_500ml_3loops_RAW_GAZBCKP.yml index 2d721c8..7590e87 100644 --- a/conf/borehole_500ml_3loops_RAW_GAZBCKP.yml +++ b/conf/borehole_500ml_3loops_RAW_GAZBCKP.yml @@ -1,17 +1,13 @@ -building_name: batiment_600m2 -North_Axis: 60 +building_name: Agence_ACF +North_Axis: 122.4 -name: borehole_3loops_PACON_CtrlDeltaSP -suffix: 500ml_30KWPAC_Boiler45KW_nocond_SIGNLE_SP7040 +name: borehole_3loops_CtrldeltaSP +suffix: 500ml_30KWPAC_Boiler45KW_SP7040 verbose: 0 os_ep_path: "C:/openstudioapplication-1.8.0/EnergyPlus" -schedules: - cooling: - mode: "compact" - zones: - "RDC" - "RPLUS1" @@ -78,7 +74,8 @@ controls: soil_loop: setpoint: constant_set_point - operation: [borehole] + operation: + uncontrolled: [borehole] branches: plant: [soil_pump, borehole] demand: [hpwtw] @@ -110,7 +107,7 @@ zone_water_heating_loop: - [baseboards_RPLUS1] constant_set_point: - temp: -10 + temp: 12 water_law_set_point_7040: Setpoint_at_Outdoor_Low_Temperature: 70 diff --git a/conf/borehole_500ml_tubes.yml b/conf/borehole_500ml_tubes.yml index 1894986..a180eb8 100644 --- a/conf/borehole_500ml_tubes.yml +++ b/conf/borehole_500ml_tubes.yml @@ -1,6 +1,7 @@ -building_name: batiment_600m2 +building_name: Agence_ACF +North_Axis: 122.4 -name: borehole_500ml_reducedFlow30_80% +name: borehole_500ml_reducedFlow30_80 suffix: SP5535 os_ep_path: "C:/openstudioapplication-1.8.0/EnergyPlus" @@ -61,7 +62,7 @@ water_heating_loop: - [baseboards_RPLUS1] constant_set_point: - temp: -10 + temp: 12 water_law_set_point: Setpoint_at_Outdoor_Low_Temperature: 55 diff --git a/conf/borehole_500ml_tubes_w_gas_backup.yml b/conf/borehole_500ml_tubes_w_gas_backup.yml index 5427c58..3946236 100644 --- a/conf/borehole_500ml_tubes_w_gas_backup.yml +++ b/conf/borehole_500ml_tubes_w_gas_backup.yml @@ -1,4 +1,5 @@ -building_name: batiment_600m2 +building_name: Agence_ACF +North_Axis: 122.4 name: borehole_500ml_gaz_load_op_ctrl suffix: SP7040 @@ -41,7 +42,8 @@ controls: soil_loop: setpoint: constant_set_point - operation: [borehole] + operation: + uncontrolled: [borehole] branches: plant: [soil_pump, borehole] demand: [hpwtw] @@ -63,7 +65,7 @@ water_heating_loop: - [baseboards_RPLUS1] constant_set_point: - temp: -10 + temp: 12 water_law_set_point: Setpoint_at_Outdoor_Low_Temperature: 70 diff --git a/conf/gaz_heater.yml b/conf/gaz_heater.yml index aec56f7..499b321 100644 --- a/conf/gaz_heater.yml +++ b/conf/gaz_heater.yml @@ -1,4 +1,5 @@ -building_name: batiment_600m2 +building_name: Agence_ACF +North_Axis: 122.4 name: gaz_boiler suffix: single_loop_slow_flow diff --git a/configuration.yml b/configuration.yml index f946c53..7c42cfb 100644 --- a/configuration.yml +++ b/configuration.yml @@ -1,4 +1,5 @@ -building_name: batiment_600m2 +building_name: Agence_ACF +North_Axis: 122.4 name: borehole_1000ml suffix: SP5535 @@ -44,7 +45,7 @@ water_heating_loop: - [baseboards_RPLUS1] constant_set_point: - temp: -10 + temp: 12 water_law_set_point: Setpoint_at_Outdoor_Low_Temperature: 55 From 5ccb88ee25f6f6d7fbbf689cf6683cc5503c6d15 Mon Sep 17 00:00:00 2001 From: Alexandre CUER Date: Wed, 1 Jul 2026 22:57:11 +0200 Subject: [PATCH 2/3] hydronic cooling through fcu --- conf/SVG_500ml_3loops_RAW_GAZBCKP_FCU.yml | 162 +++++++++++++++++++ generate_hvac.py | 124 ++++++++++++--- src/idfhub/common.py | 24 +++ src/idfhub/hvac24_1_0_hydronic_cooling.py | 184 ++++++++++++++++++++++ 4 files changed, 469 insertions(+), 25 deletions(-) create mode 100644 conf/SVG_500ml_3loops_RAW_GAZBCKP_FCU.yml create mode 100644 src/idfhub/hvac24_1_0_hydronic_cooling.py diff --git a/conf/SVG_500ml_3loops_RAW_GAZBCKP_FCU.yml b/conf/SVG_500ml_3loops_RAW_GAZBCKP_FCU.yml new file mode 100644 index 0000000..79f0d32 --- /dev/null +++ b/conf/SVG_500ml_3loops_RAW_GAZBCKP_FCU.yml @@ -0,0 +1,162 @@ +building_name: Agence_ACF +North_Axis: 122.4 + +name: SVG_3loops_CtrldeltaSP +suffix: 500ml_30KWPAC_Boiler45KW_SP7040_FCU + +verbose: 0 + +os_ep_path: "C:/openstudioapplication-1.8.0/EnergyPlus" + +run_period: + Begin_Month: 4 + Begin_Day_of_Month: 21 + Begin_Year: 2026 + End_Month: 4 + End_Day_of_Month: 20 + End_Year: 2027 + +schedules: + cooling: + mode: "compact" + #standby: 30 + from: 04/21 # month/day + to: 10/15 + +zones: + - "RDC" + - "RPLUS1" + +loops: + - soil_loop + - pac_water_heating_loop + - zone_water_heating_loop + +equipments: + - borehole + - soil_pump + - hpwtw + - gas_boiler + - pac_variable_pump + - zone_variable_pump + - HX + - baseboards_RDC + - baseboards_RPLUS1 + - fcu_RDC + - fcu_RPLUS1 + - PV_lab + +sensors: + outdoorT: + type: "Site Outdoor Air Drybulb Temperature" + borehole_t: + type: "System Node Temperature" + loop: soil_loop + side: plant + port: inlet + pac_outlet: + location_name: hpwtw_load_side_outlet_node + type: "System Node Temperature" + setpoint_sensor: + location_name: pac_water_heating_loop_plant_outlet_node + type: "System Node Setpoint Temperature" + +process: + deltaSP: "setpoint_sensor - pac_outlet" + +controls: + boiler_availability: + sensor: deltaSP + type: "On/Off Supervisory" + pilot: [gas_boiler] + start_above: 0 + stop_below: 0 + +soil_loop: + setpoint: constant_set_point + operation: + uncontrolled: [borehole] + branches: + plant: [soil_pump, borehole] + demand: #[hpwtw] + - parallel: + - [hpwtw] + - [fcu_RDC] + - [fcu_RPLUS1] + Loop_Type: cooling + Design_Loop_Exit_Temperature: 12 + Loop_Design_Temperature_Difference: 5 + Maximum_Loop_Temperature: 35 + Minimum_Loop_Temperature: -5 + +pac_water_heating_loop: + setpoint: water_law_set_point_7040 + #setpoints: [water_law_set_point_5535, water_law_set_point_7040] + operation: [hpwtw, gas_boiler] + Loop_Type: heating + #control_mode: ComponentSetpoint + #Load_Distribution_Scheme: Optimal + branches: + plant: [pac_variable_pump, hpwtw, gas_boiler] + demand: [HX] + +zone_water_heating_loop: + setpoint: water_law_set_point_7040 + operation: [HX] + branches: + plant: [zone_variable_pump, HX] + demand: + - parallel: + - [baseboards_RDC] + - [baseboards_RPLUS1] + +constant_set_point: + temp: 12 + +water_law_set_point_7040: + Setpoint_at_Outdoor_Low_Temperature: 70 + Outdoor_Low_Temperature: -5 + Setpoint_at_Outdoor_High_Temperature: 40 + Outdoor_High_Temperature: 15 + +borehole: + Number_of_Boreholes_in_XDirection: 5 + Number_of_Boreholes_in_YDirection: 1 + +hpwtw: + Reference_Coefficient_of_Performance: 2.5 + Reference_Heating_Capacity: 30000 + type: heatpump + +HX: + type: exchanger + Heat_Exchange_Model_Type: CounterFlow + Control_Type: OperationSchemeModulated + +gas_boiler: + force_side: Boiler_Water + Nominal_Capacity: 45000 + Nominal_Thermal_Efficiency: 0.87 + efficiency_c: 1 #0.96 + efficiency_x: 0.02 #0.04 # x=PLR + efficiency_x2: -0.04 #-0.03 + efficiency_y: -0.0003 #-0.004 # y=Twater + efficiency_y2: 0 #-0.00004 + efficiency_xy: 0 + +PV_lab: + height: 7 + altitude: -3 + surface: + - ["37+45", 0, "altitude+height"] + - ["37+45+8", 0, "altitude+height+0.45"] + - ["37+45+8", 53, "altitude+height+0.45"] + - ["37+45", 53, "altitude+height"] + +fcu_RDC: + process: "cooling" + force_side: Water + +fcu_RPLUS1: + process: "cooling" + force_side: Water diff --git a/generate_hvac.py b/generate_hvac.py index 7382c9d..8521458 100644 --- a/generate_hvac.py +++ b/generate_hvac.py @@ -18,7 +18,8 @@ OutputVariabledictionary, OutputTableSummaryreports, OutputcontrolTableStyle, OutputVariable, OutputSqlite, - FluidpropertiesGlycolconcentration,FluidpropertiesGlycolconcentrationMeta + FluidpropertiesGlycolconcentration,FluidpropertiesGlycolconcentrationMeta, + DesignspecificationOutdoorair, ) from idfhub.idf_autocomplete.v24_1_0.idf_types_short import ( TimestepType, SizingperiodDesigndayType, RunperiodType, VersionType, SimulationcontrolType, @@ -30,6 +31,7 @@ OutputTableSummaryreportsType, OutputcontrolTableStyleType, OutputVariableType, OutputSqliteType, FluidpropertiesGlycolconcentrationType, + DesignspecificationOutdoorairType, ) from idfhub.common import ( @@ -37,7 +39,8 @@ BUILDING_NAME, PROJECT_NAME, CONF, ZONES, LOOPS, EQUIPMENTS, - SCHEDULES + SCHEDULES, + RUN_PERIOD ) from idfhub.hvac24_1_0 import ( @@ -61,8 +64,8 @@ water_to_water_heatpump, air_to_water_heatpump_eir ) +from idfhub.hvac24_1_0_hydronic_cooling import fcu_cooling from idfhub.hvac24_1_0_photovoltaic import PV_plant - from idfhub.hvac24_1_0_secondary import initialise_sensors, control, compute FORMAT = ( @@ -90,8 +93,10 @@ HPATW = "hpatw" BOILER = "boiler" EXCHANGER = "HX" +FCU = "fcu" zone_equipments: dict[str, list] = {} +air_nodes: dict[str, dict[str, str]] = {} def add_variable(name, key="*"): """add a variable to the ep output""" @@ -126,7 +131,7 @@ def add_variable(name, key="*"): SizingperiodDesignday( idf, **SizingperiodDesigndayType( - Name="design_day", + Name="winter_design_day", Month=1, Day_of_Month=1, Day_Type=EPValues.WINTER_DESIGN_DAY, @@ -138,14 +143,33 @@ def add_variable(name, key="*"): ) ) +SizingperiodDesignday( + idf, + **SizingperiodDesigndayType( + Name="summer_design_day", + Month=7, + Day_of_Month=21, + Day_Type=EPValues.SUMMER_DESIGN_DAY, + Maximum_DryBulb_Temperature=38, + Daily_DryBulb_Temperature_Range=10, + Wind_Speed=2, + Wind_Direction=180, + Wetbulb_or_DewPoint_at_Maximum_DryBulb=18, + Humidity_Condition_Type="DewPoint", + Barometric_Pressure=101325 + ) +) + Runperiod( idf, **RunperiodType( Name="run period", - Begin_Month=1, - Begin_Day_of_Month=1, - End_Month=12, - End_Day_of_Month=31, + Begin_Month=RUN_PERIOD["Begin_Month"], + Begin_Day_of_Month=RUN_PERIOD["Begin_Day_of_Month"], + Begin_Year=RUN_PERIOD["Begin_Year"], + End_Month=RUN_PERIOD["End_Month"], + End_Day_of_Month=RUN_PERIOD["End_Day_of_Month"], + End_Year=RUN_PERIOD["End_Year"], Use_Weather_File_Holidays_and_Special_Days="No", Use_Weather_File_Daylight_Saving_Period="No" ) @@ -238,8 +262,10 @@ def add_variable(name, key="*"): **SizingPlantType( Plant_or_Condenser_Loop_Name=loop, Loop_Type=conf.get("Loop_Type", EPValues.HEATING).split("_")[0], - Design_Loop_Exit_Temperature=conf.get("Design_Loop_Exit_Temperature", 70), - Loop_Design_Temperature_Difference=conf.get("Loop_Design_Temperature_Difference", 10), + Design_Loop_Exit_Temperature=conf.get( + "Design_Loop_Exit_Temperature", 70), + Loop_Design_Temperature_Difference=conf.get( + "Loop_Design_Temperature_Difference", 10), Sizing_Option="NonCoincident", Zone_Timesteps_in_Averaging_Window=1, ) @@ -247,18 +273,39 @@ def add_variable(name, key="*"): def basic_zone_sizing(zone_name: str): """basic zone sizing""" + # other methods : Flow/Person + design_spec = DesignspecificationOutdoorair( + idf, + **DesignspecificationOutdoorairType( + Name=f"{zone_name}_design_spec_oa", + Outdoor_Air_Method="Flow/Zone", + Outdoor_Air_Flow_per_Person=0.007, + Outdoor_Air_Flow_per_Zone=0.1 + ) + ) + # other methods : TemperatureDifference return SizingZone( idf, **SizingZoneType( Zone_or_ZoneList_Name=zone_name, + Zone_Cooling_Design_Supply_Air_Temperature_Input_Method="SupplyAirTemperature", + Zone_Cooling_Design_Supply_Air_Temperature=14, Zone_Cooling_Design_Supply_Air_Humidity_Ratio=0.008, - Zone_Heating_Design_Supply_Air_Humidity_Ratio=0.008, + Zone_Heating_Design_Supply_Air_Temperature_Input_Method="SupplyAirTemperature", Zone_Heating_Design_Supply_Air_Temperature=40, + Zone_Heating_Design_Supply_Air_Humidity_Ratio=0.008, + Design_Specification_Outdoor_Air_Object_Name=design_spec.Name ) ) for zone in ZONES: basic_zone_sizing(zone) zone_equipments[zone] = [] + air_nodes[zone] = { + "air_inlet_node": f"{zone}_inlet_air_node", + "air_exhaust_node": f"{zone}_return_air_node" + } + +USE_AIR = 0 for equipment_name in EQUIPMENTS: if PUMP in equipment_name: @@ -299,22 +346,32 @@ def basic_zone_sizing(zone_name: str): continue if "PV" in equipment_name: PV_plant(equipment_name) - if "baseboards" in equipment_name: - try: - zone = equipment_name.split("_")[1] - except IndexError: - zone = None - if zone in ZONES: - baseboards = add_baseboard(idf, zone) - equipments[equipment_name] = baseboards - zone_equipments[zone].append(baseboards) + continue + # zone equipment + try: + zone = equipment_name.split("_")[1] + except IndexError: + zone = None + if zone in ZONES: + if "baseboards" in equipment_name: + zone_equipment = add_baseboard(idf, zone) + equipments[equipment_name] = zone_equipment + if FCU in equipment_name: + coil_cooling_water, zone_equipment = fcu_cooling( + equipment_name, + zone_air_inlet_node=air_nodes[zone]["air_inlet_node"], + zone_air_exhaust_node=air_nodes[zone]["air_exhaust_node"] + ) + USE_AIR = 1 + equipments[equipment_name] = coil_cooling_water + zone_equipments[zone].append(zone_equipment) #---------------------------------------------------------------- # ZONE EQUIPMENTS DECLARATION #---------------------------------------------------------------- for zone, equipment_list in zone_equipments.items(): zone_equipment_list = zone_list(zone, equipment_list) - ZonehvacEquipmentconnections( + connections = ZonehvacEquipmentconnections( idf, **ZonehvacEquipmentconnectionsType( Zone_Name=zone, @@ -322,6 +379,9 @@ def basic_zone_sizing(zone_name: str): Zone_Air_Node_Name=f"{zone}_air_node" ) ) + if USE_AIR: + connections["Zone_Air_Inlet_Node_or_NodeList_Name"]=air_nodes[zone]["air_inlet_node"] + connections["Zone_Air_Exhaust_Node_or_NodeList_Name"]=air_nodes[zone]["air_exhaust_node"] sensors = initialise_sensors(CONF.get("sensors", {})) process = CONF.get("process", {}) @@ -402,8 +462,14 @@ def basic_zone_sizing(zone_name: str): # tout ce tuning des variables de sortie peut être raisonnablement fait avec IDFEditor add_variable("Site Outdoor Air Drybulb Temperature") +add_variable("Site Outdoor Air Humidity Ratio") +add_variable("Site Outdoor Air Relative Humidity") add_variable("Zone Air Temperature") +add_variable("Zone Air Relative Humidity") +add_variable("Zone Air Humidity Ratio") add_variable("Zone Thermostat Heating Setpoint Temperature") +add_variable("Zone Mean Air Dewpoint Temperature") + if CONF.get("verbose"): add_variable("System Node Setpoint Temperature") add_variable("System Node Temperature") @@ -437,10 +503,18 @@ def basic_zone_sizing(zone_name: str): add_variable("Fluid Heat Exchanger Loop Demand Side Mass Flow Rate") add_variable("Fluid Heat Exchanger Loop Demand Side Inlet Temperature") add_variable("Fluid Heat Exchanger Loop Demand Side Outlet Temperature") - -add_variable("Baseboard Total Heating Rate") -add_variable("Baseboard Water Inlet Temperature") -add_variable("Baseboard Water Outlet Temperature") + if FCU in equipment_name: + add_variable("Heating Coil Heating Rate") + add_variable("Cooling Coil Total Cooling Rate") + add_variable("Cooling Coil Sensible Cooling Rate") + add_variable("Fan Electricity Rate") + add_variable("Fan Coil Fan Electricity Rate") + add_variable("Fan Coil Heating Rate") + add_variable("Fan Coil Total Cooling Rate") + if "baseboard" in equipment_name: + add_variable("Baseboard Total Heating Rate") + add_variable("Baseboard Water Inlet Temperature") + add_variable("Baseboard Water Outlet Temperature") add_variable("Pump Mass Flow Rate") diff --git a/src/idfhub/common.py b/src/idfhub/common.py index 4e532ef..02285b3 100644 --- a/src/idfhub/common.py +++ b/src/idfhub/common.py @@ -184,3 +184,27 @@ def _eval(node): continue for key, value in sched_conf.items(): SCHEDULES[sched_name][key] = value + +RUN_PERIOD = CONF.get("run_period", {}) + +required = [ + "Begin_Month", + "Begin_Day_of_Month", + "Begin_Year", + "End_Month", + "End_Day_of_Month", + "End_Year" +] + +DEF_RUN_PERIOD = { + "Begin_Month": 1, + "Begin_Day_of_Month": 1, + "Begin_Year": 2026, + "End_Month": 12, + "End_Day_of_Month": 31, + "End_Year": 2026 +} + +for el in required: + if el not in RUN_PERIOD: + RUN_PERIOD[el] = DEF_RUN_PERIOD[el] diff --git a/src/idfhub/hvac24_1_0_hydronic_cooling.py b/src/idfhub/hvac24_1_0_hydronic_cooling.py new file mode 100644 index 0000000..d9147f3 --- /dev/null +++ b/src/idfhub/hvac24_1_0_hydronic_cooling.py @@ -0,0 +1,184 @@ +"""hvac four pipe fan coil (and two pipe also) + +# Capacity_Control_Method +Si le ventilateur tourne toujours à la même vitesse et que seule la vanne d'eau froide module : ConstantFanVariableFlow +Si vanne On/Off et fan Petite/Moyenne/Grande vitesse : MultiSpeedFan +Si moteur EC/vitesse variable continue/vanne modulante : VariableFanVariableFlow + + +Pour une zone : +Zone Air Node = air mélangé de la pièce, référence, n'est pas un node de connexion +zone_air_inlet_node = là où les équipements soufflent +zone_air_exhaust_node = là où les équipements prélèvent + +Pour le Fan, on prend 120 Pa de pressure rise, parce que le système est local (zone HVAC) +- peu de pertes réseau +- seulement une batterie eau glacée, une grille de soufflage et un petit plénum (volume air “tampon”) +pour les vitesses : +- petite vitesse ≈ confort nuit / faible charge +- moyenne ≈ régime normal +- grande ≈ pointe +""" +from typing import Tuple +from eppy.bunch_subclass import EpBunch + +from idfhub.idf_autocomplete.v24_1_0.idf_helpers_short import ( + ZonehvacFourpipefancoil, + FanSystemmodel, + CoilCoolingWater, + CoilHeatingElectric, + OutdoorairMixer, + OutputVariable, + OutdoorairNode, +) + +from idfhub.idf_autocomplete.v24_1_0.idf_types_short import ( + ZonehvacFourpipefancoilType, + FanSystemmodelType, + CoilCoolingWaterType, + CoilHeatingElectricType, + OutdoorairMixerType, + OutputVariableType, + OutdoorairNodeType, +) + +from idfhub.common import idf +from idfhub.hvac24_1_0 import ( + EPValues, + schedule_typelimits, summer, + constant_schedule, two_season_schedule +) + +def fcu_cooling( + name: str, + *, + zone_air_inlet_node: str, + zone_air_exhaust_node: str +) -> Tuple[EpBunch, EpBunch]: + """ventilo convecteur + FCU : Fan Coil Unit + Le FCU : + - puise sur le zone_exhaust_air, + - le mixe à l'air extérieur, le fait passer dans le fan, + - le raffraichit avec la CC = coil cooling + - rejette vers zone_air_inlet""" + zone_name = name.split("_")[1] + # le noeud de l'air extérieur + oa_in_node = f"{name} OA in node" + zone_oa_mixer_outlet = f"{zone_name} mixer outlet node" + node_names = [ + oa_in_node, + zone_air_exhaust_node, + zone_oa_mixer_outlet, + zone_air_inlet_node, + ] + for node_name in node_names: + OutputVariable( + idf, + **OutputVariableType( + Key_Value=node_name, + Variable_Name="System Node Temperature", + Reporting_Frequency="Timestep" + ) + ) + mixer = OutdoorairMixer( + idf, + **OutdoorairMixerType( + Name=f"{name} OA mixer", + Mixed_Air_Node_Name= zone_oa_mixer_outlet, + Outdoor_Air_Stream_Node_Name=oa_in_node, + Relief_Air_Stream_Node_Name=f"{name} Exh node", + Return_Air_Stream_Node_Name=zone_air_exhaust_node + ) + ) + OutdoorairNode( + idf, + **OutdoorairNodeType( + Name=oa_in_node + ) + ) + fan = FanSystemmodel( + idf, + **FanSystemmodelType( + Name=f"{name}_fan", + Air_Inlet_Node_Name=zone_oa_mixer_outlet, + Air_Outlet_Node_Name=f"{name}_fan_outlet", + Design_Maximum_Air_Flow_Rate=EPValues.AUTOSIZE, + Design_Pressure_Rise=120, + Motor_Efficiency=0.8, + Number_of_Speeds=3, + Speed_1_Flow_Fraction=0.33, + Speed_2_Flow_Fraction=0.66, + Speed_3_Flow_Fraction=1, + Speed_1_Electric_Power_Fraction=0.3, + Speed_2_Electric_Power_Fraction=0.65, + Speed_3_Electric_Power_Fraction=1 + ) + ) + # availability schedule + # typelimits are initialized in generate_hvac + # so this part is not really needed + schedule_typelimits( + EPValues.FRACTIONAL, + lower_limit=0, upper_limit=1 + ) + summer_start, summer_end = summer() + if summer_start and summer_end: + fan_schedule = two_season_schedule( + name=f"common_summer_fan_schedule", + period_start=summer_start, + period_end=summer_end, + value_on_period=1, + value_out_period=0, + typelimits_name=EPValues.FRACTIONAL + ) + fan["Availability_Schedule_Name"] = fan_schedule.Name + coil_cooling_water = CoilCoolingWater( + idf, + **CoilCoolingWaterType( + Name=f"{name}_coil_cooling_water", + Water_Inlet_Node_Name=f"{name}_water_inlet", + Water_Outlet_Node_Name=f"{name}_water_outlet", + Air_Inlet_Node_Name=f"{name}_fan_outlet", + Air_Outlet_Node_Name=f"{name}_CC_water_air_outlet" + ) + ) + always_off = "Always OFF" + constant_schedule( + 0, typelimits_name=EPValues.FRACTIONAL, + name = always_off + ) + coil_heating_electric = CoilHeatingElectric( + idf, + **CoilHeatingElectricType( + Name=f"{name}_coil_heating_electric", + Air_Inlet_Node_Name=f"{name}_CC_water_air_outlet", + Air_Outlet_Node_Name=zone_air_inlet_node, + Availability_Schedule_Name=always_off + ) + ) + # other control methods + # ConstantFanVariableFlow < pour les FanConstantVolume + # CyclingFan < pour les FanOnOff + fcu = ZonehvacFourpipefancoil( + idf, + **ZonehvacFourpipefancoilType( + Name=name, + Capacity_Control_Method="MultiSpeedFan", + Maximum_Supply_Air_Flow_Rate=EPValues.AUTOSIZE, + Maximum_Outdoor_Air_Flow_Rate=EPValues.AUTOSIZE, + Outdoor_Air_Mixer_Object_Type=mixer.key, + Outdoor_Air_Mixer_Name=mixer.Name, + Air_Inlet_Node_Name=zone_air_exhaust_node, + Air_Outlet_Node_Name=zone_air_inlet_node, + Supply_Air_Fan_Name=fan.Name, + Supply_Air_Fan_Object_Type=fan.key, + Cooling_Coil_Name=coil_cooling_water.Name, + Cooling_Coil_Object_Type=coil_cooling_water.key, + Maximum_Cold_Water_Flow_Rate=EPValues.AUTOSIZE, + Heating_Coil_Name=coil_heating_electric.Name, + Heating_Coil_Object_Type=coil_heating_electric.key, + Maximum_Hot_Water_Flow_Rate=EPValues.AUTOSIZE + ) + ) + return coil_cooling_water, fcu From b848b614c28fc826ff2621299349849b6aa3ddad Mon Sep 17 00:00:00 2001 From: Alexandre CUER Date: Thu, 2 Jul 2026 13:41:19 +0200 Subject: [PATCH 3/3] monitor air flow and speed fan --- generate_hvac.py | 1 + src/idfhub/hvac24_1_0_hydronic_cooling.py | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/generate_hvac.py b/generate_hvac.py index 8521458..046db29 100644 --- a/generate_hvac.py +++ b/generate_hvac.py @@ -511,6 +511,7 @@ def basic_zone_sizing(zone_name: str): add_variable("Fan Coil Fan Electricity Rate") add_variable("Fan Coil Heating Rate") add_variable("Fan Coil Total Cooling Rate") + add_variable("Fan Coil Fan Speed Level") if "baseboard" in equipment_name: add_variable("Baseboard Total Heating Rate") add_variable("Baseboard Water Inlet Temperature") diff --git a/src/idfhub/hvac24_1_0_hydronic_cooling.py b/src/idfhub/hvac24_1_0_hydronic_cooling.py index d9147f3..4dab76d 100644 --- a/src/idfhub/hvac24_1_0_hydronic_cooling.py +++ b/src/idfhub/hvac24_1_0_hydronic_cooling.py @@ -72,15 +72,20 @@ def fcu_cooling( zone_oa_mixer_outlet, zone_air_inlet_node, ] + rdd_variables = [ + "System Node Temperature", + "System Node Mass Flow Rate" + ] for node_name in node_names: - OutputVariable( - idf, - **OutputVariableType( - Key_Value=node_name, - Variable_Name="System Node Temperature", - Reporting_Frequency="Timestep" + for variable in rdd_variables: + OutputVariable( + idf, + **OutputVariableType( + Key_Value=node_name, + Variable_Name=variable, + Reporting_Frequency="Timestep" + ) ) - ) mixer = OutdoorairMixer( idf, **OutdoorairMixerType(