diff --git a/Facade_Engine/Compute/UValueAW.cs b/Facade_Engine/Compute/UValueAW.cs new file mode 100644 index 000000000..feff344a6 --- /dev/null +++ b/Facade_Engine/Compute/UValueAW.cs @@ -0,0 +1,91 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.oM.Geometry; +using BH.oM.Dimensional; +using System; +using System.Collections.Generic; +using System.Linq; +using BH.oM.Facade; +using BH.oM.Facade.Elements; +using BH.oM.Base; +using BH.Engine.Geometry; +using BH.Engine.Spatial; +using BH.Engine.Base; +using BH.oM.Facade.Fragments; + +using BH.oM.Base.Attributes; +using BH.oM.Facade.Results; +using System.ComponentModel; + +namespace BH.Engine.Facade +{ + public static partial class Compute + { + /***************************************************/ + /**** Public Methods ****/ + /***************************************************/ + + [Description("Returns effective U-Value of a collection of Facade objects calculated using the Area Weighting Method. Requires center of opening U-value, frame U-value and edge U-value as OpeningConstruction and FrameEdgeProperty fragments for Openings, and UValueContinuous fragment for Panels.")] + [Input("objs", "Objects to find U-value for.")] + [Output("effectiveUValue", "Effective total U-value result of objects calculated using area weighting.")] + public static OverallUValue UValueAW(this List objs) + { + double uValueProduct = 0; + double totalArea = 0; + foreach (IFacadeObject obj in objs) + { + double area = 0; + double uValue = 0; + if (obj is Panel panel) + { + area = panel.Area(); + uValue = UValuePanelAW(panel).UValue; + } + else if (obj is Opening opening) + { + area = opening.Area(); + uValue = UValueOpeningAW(opening).UValue; + } + else + { + Base.Compute.RecordWarning($"Object {obj.BHoM_Guid} is of a type currently not supported for UValue methods. It has been excluded from the calculation."); + continue; + } + uValueProduct += uValue * area; + totalArea += area; + } + if (totalArea == 0) + { + Base.Compute.RecordError("Objects have a total calculated area of 0. Ensure Objects are valid with associated edges defining their geometry and try again."); + return null; + } + + double effectiveUValue = uValueProduct / totalArea; + OverallUValue result = new OverallUValue(effectiveUValue, objs.Select(x => x.BHoM_Guid as IComparable).ToList()); + return result; + } + + /***************************************************/ + + } +} \ No newline at end of file diff --git a/Facade_Engine/Compute/UValueOpeningAW.cs b/Facade_Engine/Compute/UValueOpeningAW.cs index 68883ecb9..893122aba 100644 --- a/Facade_Engine/Compute/UValueOpeningAW.cs +++ b/Facade_Engine/Compute/UValueOpeningAW.cs @@ -56,7 +56,6 @@ public static OverallUValue UValueOpeningAW(this Opening opening) } List glassUValues = opening.OpeningConstruction.GetAllFragments(typeof(UValueGlassCentre)); - if (glassUValues.Count <= 0) { BH.Engine.Base.Compute.RecordError($"Opening {opening.BHoM_Guid} does not have Glass U-value assigned."); @@ -82,6 +81,18 @@ public static OverallUValue UValueOpeningAW(this Opening opening) } double glassEdgeUValue = (glassEdgeUValues[0] as UValueGlassEdge).UValue; + double contUValue = 0; + List contUValues = opening.OpeningConstruction.GetAllFragments(typeof(UValueContinuous)); + if (contUValues.Count == 1) + { + contUValue = (contUValues[0] as UValueContinuous).UValue; + } + if (contUValues.Count > 1) + { + Base.Compute.RecordError($"Opening {opening.BHoM_Guid} has more than one continuous U-value assigned."); + return null; + } + List frameEdges = opening.Edges; List frameAreas = new List(); List frameUValues = new List(); @@ -154,7 +165,18 @@ public static OverallUValue UValueOpeningAW(this Opening opening) { BH.Engine.Base.Compute.RecordError($"Opening {opening.BHoM_Guid} has a calculated area of 0. Ensure the opening is valid with associated edges defining its geometry and try again."); } - double effectiveUValue = (((glassArea * glassUValue) + EdgeUValProduct + FrameUValProduct) / totArea); + + double baseUValue = (((glassArea * glassUValue) + EdgeUValProduct + FrameUValProduct) / totArea); + double effectiveUValue = 0; + if (contUValue == 0) + { + effectiveUValue = baseUValue; + } + else + { + effectiveUValue = 1 / (1 / baseUValue + 1 / contUValue); + } + OverallUValue result = new OverallUValue (effectiveUValue, new List { opening.BHoM_Guid }); return result; } diff --git a/Facade_Engine/Compute/UValuePanelAW.cs b/Facade_Engine/Compute/UValuePanelAW.cs new file mode 100644 index 000000000..e40d9fb02 --- /dev/null +++ b/Facade_Engine/Compute/UValuePanelAW.cs @@ -0,0 +1,130 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.oM.Geometry; +using BH.oM.Dimensional; +using System; +using System.Collections.Generic; +using System.Linq; +using BH.oM.Facade.Elements; +using BH.oM.Base; +using BH.Engine.Geometry; +using BH.Engine.Spatial; +using BH.Engine.Base; +using BH.oM.Facade.Fragments; +using BH.oM.Facade.Results; + +using BH.oM.Base.Attributes; +using System.ComponentModel; + +namespace BH.Engine.Facade +{ + public static partial class Compute + { + /***************************************************/ + /**** Public Methods ****/ + /***************************************************/ + + [Description("Returns effective U-Value of panel calculated using the Area Weighting Method. Requires continuous U-value as Construction fragment.")] + [Input("panel", "Panel to find U-value for.")] + [Output("effectiveUValue", "Effective U-value result of panel calculated using area weighting.")] + public static OverallUValue UValuePanelAW(this Panel panel) + { + if (panel == null) + { + Base.Compute.RecordError($"U-Value can not be calculated for null panel."); + return null; + } + + List glassUValues = panel.Construction.GetAllFragments(typeof(UValueGlassCentre)); + if (glassUValues.Count > 0) + { + BH.Engine.Base.Compute.RecordError($"Panel {panel.BHoM_Guid} has Glass U-value assigned. Panels can only receive Continuous U-value"); + return null; + } + + List glassEdgeUValues = panel.Construction.GetAllFragments(typeof(UValueGlassEdge)); + if (glassEdgeUValues.Count > 0) + { + BH.Engine.Base.Compute.RecordError($"Panel {panel.BHoM_Guid} has Glass edge U-value assigned. Panels can only receive Continuous U-value"); + return null; + } + + List contUValues = panel.Construction.GetAllFragments(typeof(UValueContinuous)); + if (contUValues.Count <= 0) + { + Base.Compute.RecordError($"Panel {panel.BHoM_Guid} does not have Continuous U-value assigned."); + return null; + } + if (contUValues.Count > 1) + { + Base.Compute.RecordError($"Panel {panel.BHoM_Guid} has more than one Continuous U-value assigned."); + return null; + } + double contUValue = (contUValues[0] as UValueContinuous).UValue; + + List frameEdges = panel.ExternalEdges; + List frameUValues = new List(); + for (int i = 0; i < frameEdges.Count; i++) + { + List f_uValues = frameEdges[i].FrameEdgeProperty.GetAllFragments(typeof(UValueFrame)); + if (f_uValues.Count > 0) + { + Engine.Base.Compute.RecordWarning($"Panel {panel.BHoM_Guid} has Frame U-value assigned. Frame U-values are not included in calculation."); + continue; + } + } + + double panelArea = panel.Area(); + if (panelArea == 0) + { + BH.Engine.Base.Compute.RecordError($"Panel {panel.BHoM_Guid} has a calculated area of 0. Ensure the panel is valid with associated edges defining its geometry and try again."); + } + double panelUValue = contUValue; + double effectiveUValue = panelUValue; + + List panelOpenings = panel.Openings; + if (panelOpenings.Count > 0) + { + double uValueProduct = panelUValue * panelArea; + double totalArea = panelArea; + foreach (Opening opening in panelOpenings) + { + double area = opening.Area(); + uValueProduct += opening.UValueOpeningAW().UValue * area; + totalArea += area; + } + if (totalArea == 0) + { + Base.Compute.RecordError("Openings have a total calculated area of 0. Ensure Openings are valid with associated edges defining their geometry and try again."); + return null; + } + effectiveUValue = uValueProduct / totalArea; + } + OverallUValue result = new OverallUValue(effectiveUValue, new List { panel.BHoM_Guid }); + return result; + } + + /***************************************************/ + + } +} \ No newline at end of file