Skip to content

Commit

Permalink
EC-54 add edit_thermal_bridging function to FHS notional wrapper
Browse files Browse the repository at this point in the history
Co-Authored-By: Korinna Pinakoulakis <[email protected]>
  • Loading branch information
shieldo and kpinakula committed Oct 18, 2024
1 parent 3fa0881 commit 1f12154
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 8 deletions.
35 changes: 31 additions & 4 deletions src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1797,7 +1797,7 @@ pub(crate) trait GroundBuildingElement {
impl GroundBuildingElement for BuildingElement {
fn set_u_value(&mut self, new_u_value: f64) {
match self {
Self::Ground { u_value, ..} => {
Self::Ground { u_value, .. } => {
*u_value = new_u_value;
}
_ => unreachable!(),
Expand All @@ -1815,7 +1815,10 @@ impl GroundBuildingElement for BuildingElement {

fn set_psi_wall_floor_junc(&mut self, new_psi_wall_floor_junc: f64) {
match self {
Self::Ground { psi_wall_floor_junc, .. } => {
Self::Ground {
psi_wall_floor_junc,
..
} => {
*psi_wall_floor_junc = new_psi_wall_floor_junc;
}
_ => unreachable!(),
Expand Down Expand Up @@ -1982,7 +1985,6 @@ pub enum ThermalBridgingDetails {
Linear {
linear_thermal_transmittance: f64,
length: f64,
#[allow(dead_code)]
junction_type: Option<String>,
},
#[serde(rename = "ThermalBridgePoint")]
Expand Down Expand Up @@ -2868,6 +2870,29 @@ impl InputForProcessing {
.area)
}

#[cfg(test)]
pub(crate) fn all_thermal_bridgings(&self) -> Vec<&ThermalBridging> {
self.input
.zone
.values()
.map(|z| &z.thermal_bridging)
.collect::<Vec<_>>()
}

pub(crate) fn all_thermal_bridging_elements(
&mut self,
) -> Vec<&mut IndexMap<String, ThermalBridgingDetails>> {
self.input
.zone
.values_mut()
.map(|z| &mut z.thermal_bridging)
.filter_map(|el| match el {
ThermalBridging::ThermalBridgingElements(ref mut elements) => Some(elements),
ThermalBridging::ThermalBridgingNumber(_) => None,
})
.collect::<Vec<&mut IndexMap<String, ThermalBridgingDetails>>>()
}

pub fn number_of_bedrooms(&self) -> Option<usize> {
self.input.number_of_bedrooms
}
Expand Down Expand Up @@ -3485,7 +3510,9 @@ impl InputForProcessing {
.collect()
}

pub(crate) fn all_ground_building_elements_mut(&mut self) -> Vec<&mut impl GroundBuildingElement> {
pub(crate) fn all_ground_building_elements_mut(
&mut self,
) -> Vec<&mut impl GroundBuildingElement> {
self.input
.zone
.values_mut()
Expand Down
132 changes: 128 additions & 4 deletions src/wrappers/future_homes_standard/future_homes_standard_notional.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ use crate::{
units::{LITRES_PER_CUBIC_METRE, SECONDS_PER_HOUR},
},
input::{
HeatPumpSourceType,
GroundBuildingElement, HeatPumpSourceType,
HeatSourceWetDetails::{HeatPump, Hiu},
InputForProcessing, UValueEditableBuildingElement, GroundBuildingElement
InputForProcessing, ThermalBridgingDetails, UValueEditableBuildingElement,
},
wrappers::future_homes_standard::future_homes_standard::calc_tfa,
};
use anyhow::bail;
use anyhow::{anyhow, bail};
use itertools::Itertools;
use std::collections::HashMap;
use std::sync::LazyLock;

/// Apply assumptions and pre-processing steps for the Future Homes Standard Notional building
fn apply_fhs_not_preprocessing(
Expand Down Expand Up @@ -145,6 +147,87 @@ pub(crate) fn edit_ground_floors(input: &mut InputForProcessing) -> anyhow::Resu
Ok(())
}

/// The notional building must follow the same thermal bridges as specified in
/// SAP10.2 Table R2
///
/// TODO - how to deal with ThermalBridging when lengths are not specified?
pub(crate) fn edit_thermal_bridging(input: &mut InputForProcessing) -> anyhow::Result<()> {
let mut thermal_bridging_elements = input.all_thermal_bridging_elements();

for element in thermal_bridging_elements
.iter_mut()
.flat_map(|group| group.values_mut())
{
match element {
ThermalBridgingDetails::Point {
heat_transfer_coefficient,
..
} => {
*heat_transfer_coefficient = 0.;
}
ThermalBridgingDetails::Linear {
junction_type,
linear_thermal_transmittance,
..
} => {
let junction_type = junction_type.as_ref().and_then(|junc| if TABLE_R2.contains_key(junc.as_str()) {Some(junc.clone())} else {None}).ok_or_else(|| anyhow!("Thermal bridging junction type was expected to be set and one of the values in SAP10.2 Table R2."))?;
*linear_thermal_transmittance = TABLE_R2[junction_type.as_str()];
}
}
}

Ok(())
}

static TABLE_R2: LazyLock<HashMap<&'static str, f64>> = LazyLock::new(|| {
HashMap::from([
("E1", 0.05),
("E2", 0.05),
("E3", 0.05),
("E4", 0.05),
("E5", 0.16),
("E19", 0.07),
("E20", 0.32),
("E21", 0.32),
("E22", 0.07),
("E6", 0.),
("E7", 0.07),
("E8", 0.),
("E9", 0.02),
("E23", 0.02),
("E10", 0.06),
("E24", 0.24),
("E11", 0.04),
("E12", 0.06),
("E13", 0.08),
("E14", 0.08),
("E15", 0.56),
("E16", 0.09),
("E17", -0.09),
("E18", 0.06),
("E25", 0.06),
("P1", 0.08),
("P6", 0.07),
("P2", 0.),
("P3", 0.),
("P7", 0.16),
("P8", 0.24),
("P4", 0.12),
("P5", 0.08),
("R1", 0.08),
("R2", 0.06),
("R3", 0.08),
("R4", 0.08),
("R5", 0.04),
("R6", 0.06),
("R7", 0.04),
("R8", 0.06),
("R9", 0.04),
("R10", 0.08),
("R11", 0.08),
])
});

/// Calculate effective air change rate accoring to according to Part F 1.24 a
pub fn minimum_air_change_rate(
_input: &InputForProcessing,
Expand Down Expand Up @@ -177,6 +260,7 @@ mod tests {

use super::*;
use crate::input;
use crate::input::{ThermalBridging, ThermalBridgingDetails};
use rstest::{fixture, rstest};
use std::borrow::BorrowMut;
use std::io::{BufReader, Cursor};
Expand Down Expand Up @@ -273,11 +357,51 @@ mod tests {
edit_ground_floors(test_input).unwrap();

for building_element in test_input.all_building_elements() {
if let input::BuildingElement::Ground { u_value, r_f, psi_wall_floor_junc, .. } = building_element {
if let input::BuildingElement::Ground {
u_value,
r_f,
psi_wall_floor_junc,
..
} = building_element
{
assert_eq!(*u_value, 0.13);
assert_eq!(*r_f, 6.12);
assert_eq!(*psi_wall_floor_junc, 0.16);
}
}
}

#[rstest]
fn test_edit_thermal_bridgings(mut test_input: InputForProcessing) {
let test_input = test_input.borrow_mut();

edit_thermal_bridging(test_input).unwrap();

for thermal_bridging in test_input.all_thermal_bridgings() {
match thermal_bridging {
ThermalBridging::ThermalBridgingNumber(_) => {}
ThermalBridging::ThermalBridgingElements(elements) => {
for bridging in elements.values() {
match bridging {
ThermalBridgingDetails::Point {
heat_transfer_coefficient,
..
} => {
assert_eq!(*heat_transfer_coefficient, 0.0);
}
ThermalBridgingDetails::Linear {
junction_type,
linear_thermal_transmittance,
..
} => {
let junction_type = junction_type.as_ref().unwrap().as_str();
assert!(TABLE_R2.contains_key(junction_type));
assert_eq!(*linear_thermal_transmittance, TABLE_R2[junction_type]);
}
}
}
}
}
}
}
}

0 comments on commit 1f12154

Please sign in to comment.