Skip to content

Commit

Permalink
Facade_Engine: Added continuous UValue Calc to SAM method and Overarc…
Browse files Browse the repository at this point in the history
…hing UValue Methode for Collections of Elements (#3435)
  • Loading branch information
michaelhoehn authored Dec 4, 2024
2 parents b97deef + b5d97f3 commit 5a5deb6
Show file tree
Hide file tree
Showing 5 changed files with 276 additions and 44 deletions.
20 changes: 14 additions & 6 deletions Facade_Engine/Compute/UValueAW.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,28 +55,36 @@ public static OverallUValue UValueAW(this List<IFacadeObject> objs)
foreach (IFacadeObject obj in objs)
{
double area = 0;
double uValue = 0;
double? uValue = 0;
if (obj is Panel panel)
{
area = panel.Area();
uValue = UValuePanelAW(panel).UValue;
uValue = UValuePanelAW(panel)?.UValue;
}
else if (obj is Opening opening)
{
area = opening.Area();
uValue = UValueOpeningAW(opening).UValue;
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;

if (uValue == null)
{
Base.Compute.RecordWarning($"UValue calculation failed for Object {obj.BHoM_Guid}. It has been excluded from the calculation.");
continue;
}

uValueProduct += uValue.Value * area;
totalArea += area;
}
if (totalArea == 0)

if (totalArea == 0 || uValueProduct == 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.");
Base.Compute.RecordError("No valid objects for UValue calculation were provided. Ensure Objects are valid with required UValue properties and associated edges defining their geometry and try again.");
return null;
}

Expand Down
8 changes: 8 additions & 0 deletions Facade_Engine/Compute/UValueOpeningSAM.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,16 @@ public static OverallUValue UValueOpeningSAM(this Opening opening)
BH.Engine.Base.Compute.RecordError($"Opening {opening.BHoM_Guid} has more than one U-value assigned.");
return null;
}

double uValue = (uValues[0] as UValueGlassCentre).UValue;

List<IFragment> uValuesCont = opening.OpeningConstruction.GetAllFragments(typeof(UValueContinuous));
if (uValuesCont.Count == 1)
{
double contUValue = (uValuesCont[0] as UValueContinuous).UValue;
uValue = 1 / (1 / uValue + 1 / contUValue);
}

List<FrameEdge> frameEdges = opening.Edges;
List<double> psiValues = new List<double>();
List<double> lengths = new List<double>();
Expand Down
92 changes: 54 additions & 38 deletions Facade_Engine/Compute/UValuePanelAW.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

using BH.oM.Base.Attributes;
using System.ComponentModel;
using BH.oM.Physical.Constructions;

namespace BH.Engine.Facade
{
Expand All @@ -55,40 +56,83 @@ public static OverallUValue UValuePanelAW(this Panel panel)
return null;
}

List<IFragment> glassUValues = panel.Construction.GetAllFragments(typeof(UValueGlassCentre));
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.");
return null;
}

double panelUValue = panel.PanelEffectiveUValue();
if (panelUValue == double.NaN)
return null;

double effectiveUValue = panelUValue;
List<Opening> 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<IComparable> { panel.BHoM_Guid });
return result;
}

/***************************************************/
/**** Helper Methods ****/
/***************************************************/

private static double PanelEffectiveUValue(this Panel panel)
{
IConstruction construction = panel.Construction;

List<IFragment> glassUValues = 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 and/or Cavity U-value.");
return null;
return double.NaN;
}

List<IFragment> glassEdgeUValues = panel.Construction.GetAllFragments(typeof(UValueGlassEdge));
List<IFragment> glassEdgeUValues = 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;
return double.NaN;
}

List<IFragment> contUValues = panel.Construction.GetAllFragments(typeof(UValueContinuous));
List<IFragment> cavityUValues = panel.Construction.GetAllFragments(typeof(UValueCavity));
List<IFragment> contUValues = construction.GetAllFragments(typeof(UValueContinuous));
List<IFragment> cavityUValues = construction.GetAllFragments(typeof(UValueCavity));
double contUValue = 0;
double cavityUValue = 0;
double panelUValue = 0;

if ((contUValues.Count <= 0) && (cavityUValues.Count <= 0))
{
Base.Compute.RecordError($"Panel {panel.BHoM_Guid} does not have Continuous U-value or Cavity U-value assigned.");
return null;
return double.NaN;
}
if (contUValues.Count > 1)
{
Base.Compute.RecordError($"Panel {panel.BHoM_Guid} has more than one Continuous U-value assigned.");
return null;
return double.NaN;
}
if (cavityUValues.Count > 1)
{
Base.Compute.RecordError($"Panel {panel.BHoM_Guid} has more than one Cavity U-value assigned.");
return null;
return double.NaN;
}
if ((contUValues.Count == 1) && (cavityUValues.Count == 1))
{
Expand Down Expand Up @@ -118,37 +162,9 @@ public static OverallUValue UValuePanelAW(this Panel panel)
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 effectiveUValue = panelUValue;

List<Opening> 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<IComparable> { panel.BHoM_Guid });
return result;
return panelUValue;
}

/***************************************************/

}
}
Expand Down
100 changes: 100 additions & 0 deletions Facade_Engine/Compute/UValuePanelSAM.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* This file is part of the Buildings and Habitats object Model (BHoM)
* Copyright (c) 2015 - 2024, 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 <https://www.gnu.org/licenses/lgpl-3.0.html>.
*/

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;
using BH.oM.Facade.SectionProperties;
using BH.oM.Quantities.Attributes;

namespace BH.Engine.Facade
{
public static partial class Compute
{
/***************************************************/
/**** Public Methods ****/
/***************************************************/

[Description("Returns effective U - Value of a panel calculated using the Single Assessment Method(Using Psi-tj). Requires center of opening U-value and frame Psi-tj value as OpeningConstruction and FrameEdgeProperty fragments on any Openings within the Panel.")]
[Input("panel", "Panel to find U-value for.")]
[Output("effectiveUValue", "Effective U-value result of panel calculated using SAM.")]
public static OverallUValue UValuePanelSAM(this Panel panel)
{
if (panel == null)
{
Base.Compute.RecordError($"U-Value can not be calculated for null panel.");
return null;
}

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.");
return null;
}

double panelUValue = panel.PanelEffectiveUValue();
if (panelUValue == double.NaN)
return null;

Base.Compute.RecordNote("Panels assessed using SAM method will use SAM method for any contained Openings, but will only assess the Panel itself based on its assigned Continuous and/or Cavity U Values.");
double effectiveUValue = panelUValue;
List<Opening> 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.UValueOpeningSAM().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<IComparable> { panel.BHoM_Guid });
return result;
}

/***************************************************/

}
}

Loading

0 comments on commit 5a5deb6

Please sign in to comment.