diff --git a/LifeCycleAssessment_Engine/Compute/EvaluateEnvironmentalProductDeclaration.cs b/LifeCycleAssessment_Engine/Compute/EvaluateEnvironmentalProductDeclaration.cs index 617aeaa..cae365a 100644 --- a/LifeCycleAssessment_Engine/Compute/EvaluateEnvironmentalProductDeclaration.cs +++ b/LifeCycleAssessment_Engine/Compute/EvaluateEnvironmentalProductDeclaration.cs @@ -30,6 +30,7 @@ using BH.oM.Physical.Materials; using BH.Engine.Matter; using BH.Engine.LifeCycleAssessment.Objects; +using BH.oM.LifeCycleAssessment.MaterialFragments; namespace BH.Engine.LifeCycleAssessment { @@ -39,21 +40,26 @@ public static partial class Compute /**** Public Methods ****/ /***************************************************/ + [PreviousVersion("6.0", "BH.Engine.LifeCycleAssessment.Compute.EvaluateEnvironmentalProductDeclaration(BH.oM.Dimensional.IElementM, System.Collections.Generic.List, BH.oM.LifeCycleAssessment.EnvironmentalProductDeclarationField, System.Boolean)")] [Description("This method calculates the results of any selected metric within an Environmental Product Declaration. For example for an EPD of QuantityType Volume, results will reflect the objects volume * EPD Field metric.")] [Input("elementM", "This is a BHoM object used to calculate EPD metric. This obj must have an EPD MaterialFragment applied to the object.")] [Input("phases", "Provide phases of life you wish to evaluate. Phases of life must be documented within EPDs for this method to work.")] [Input("field", "Filter the provided EnvironmentalProductDeclaration by selecting one of the provided metrics for calculation. This method also accepts multiple fields simultaneously.")] [Input("exactMatch", "If true, the evaluation method will force an exact LCA phase match to solve for.")] [Output("result", "A LifeCycleElementResult that contains the LifeCycleAssessment data for the input object.")] - public static LifeCycleAssessmentElementResult EvaluateEnvironmentalProductDeclaration(IElementM elementM, List phases, EnvironmentalProductDeclarationField field = EnvironmentalProductDeclarationField.GlobalWarmingPotential, bool exactMatch = false) + public static LifeCycleAssessmentElementResult EvaluateEnvironmentalProductDeclaration(IElementM elementM, List phases, EnvironmentalProductDeclarationField field = EnvironmentalProductDeclarationField.GlobalWarmingPotential, bool exactMatch = false, List templateMaterials = null, bool prioritiseTemplate = true) { double value = 0; EnvironmentalMetricResult resultValue = null; - MaterialComposition mc = elementM.IMaterialComposition(); + MaterialComposition mc = elementM.MappedMaterialComposition(templateMaterials, true, prioritiseTemplate); - List qts = elementM.GetQuantityType(mc); - - qts = qts.Distinct().ToList(); + List qts = mc.Materials.Where(x => x != null).Select(x => + { + var epd = x.Properties.OfType().FirstOrDefault(); + if (epd != null) + return epd.QuantityType; + return QuantityType.Undefined; + }).Distinct().ToList(); foreach (QuantityType qt in qts) { @@ -115,8 +121,8 @@ public static LifeCycleAssessmentElementResult EvaluateEnvironmentalProductDecla resultValue.EnvironmentalProductDeclaration = elementM.GetElementEpd(mc); return resultValue; } - /***************************************************/ + /***************************************************/ } } diff --git a/LifeCycleAssessment_Engine/Compute/EvaluateEnvironmentalProductDeclarationByMass.cs b/LifeCycleAssessment_Engine/Compute/EvaluateEnvironmentalProductDeclarationByMass.cs index 6e1bf71..95a8c38 100644 --- a/LifeCycleAssessment_Engine/Compute/EvaluateEnvironmentalProductDeclarationByMass.cs +++ b/LifeCycleAssessment_Engine/Compute/EvaluateEnvironmentalProductDeclarationByMass.cs @@ -51,7 +51,6 @@ private static EnvironmentalMetricResult EvaluateEnvironmentalProductDeclaration { double volume = elementM.ISolidVolume(); List gwpByMaterial = new List(); - List matList = materialComposition.Materials.ToList(); List epdVals = elementM.GetEvaluationValue(field, phases, QuantityType.Mass, materialComposition, exactMatch); if (epdVals == null || epdVals.Where(x => !double.IsNaN(x)).Sum() <= 0) @@ -60,27 +59,31 @@ private static EnvironmentalMetricResult EvaluateEnvironmentalProductDeclaration return null; } - for (int i = 0; i < matList.Count(); i++) + for (int i = 0; i < materialComposition.Materials.Count; i++) { - double density; - List materialEPDs = matList[i].Properties.OfType().ToList(); + List materialEPDs = materialComposition.Materials[i].Properties.OfType().ToList(); if (materialEPDs.Any(x => x.QuantityType == QuantityType.Mass)) { double volumeOfMaterial = materialComposition.Ratios[i] * volume; - List densityOfMassEpd = materialEPDs.Where(x => x.QuantityType == QuantityType.Mass).First().GetEPDDensity(); - if (densityOfMassEpd == null || densityOfMassEpd.Count() == 0) + double density = materialComposition.Materials[i].Density; + if (double.IsNaN(density)) { - BH.Engine.Base.Compute.RecordError("Density could not be found. Add DensityFragment for all objects using Mass-based QuantityType EPDs."); + Engine.Base.Compute.RecordError($"Density of material {materialComposition.Materials[i].Name} is not set (NaN). Ensure all materials have densities assigned when computing {field} for mass-based {nameof(QuantityType)}s."); return null; } + else if (density == 0) + { + Engine.Base.Compute.RecordWarning($"Density of material {materialComposition.Materials[i].Name} is 0 and will lead to no contribution to the computation of {field}."); + gwpByMaterial.Add(0); + } else - density = densityOfMassEpd[0]; - - double massOfObj = volumeOfMaterial * density; - if (double.IsNaN(epdVals[i])) - gwpByMaterial.Add(double.NaN); - else - gwpByMaterial.Add(epdVals[i] * massOfObj); + { + double massOfObj = volumeOfMaterial * density; + if (double.IsNaN(epdVals[i])) + gwpByMaterial.Add(double.NaN); + else + gwpByMaterial.Add(epdVals[i] * massOfObj); + } } } ScopeType scope = BH.Engine.LifeCycleAssessment.Query.GetElementScope(elementM);