Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Glazing/Opaque/Gas]Material to_epbunch overwrites other objects with same material but different thickness #459

Open
szvsw opened this issue May 14, 2023 · 0 comments
Labels
help wanted Extra attention is needed

Comments

@szvsw
Copy link
Collaborator

szvsw commented May 14, 2023

This is a pretty significant one in terms of impact but a trivial fix.

Problem

IDFs have no concept of layers, so thickness of course lives within Material definitions in the IDF, unlike Archetypal, where thickness lives in the MaterialLayer. When constructions are added to an IDF, they add their underlying materials with the designated thickness but only use the materials' names as the IDF object name. This results in erroneous propagation of thicknesses to any other constructions which use the same material but different thickness, since the older instance of the material in the IDF gets replaced with the new one due to having the same name. This would even happen within a single construction if the same material is used twice but with different thicknesses.

Code

Each of the to_epbunch methods for Glazing/Gas/OpaqueMaterial accept a thickness (usually passed in when an [Opaque/Glazing]Construction object's call to to_epbunch in turn invokes the to_epbunch method of each of the underlying XMaterial objects in the construction's Layers list), e.g. here:

return idf.newidfobject(
key="CONSTRUCTION",
Name=self.Name,
Outside_Layer=self.Layers[0].to_epbunch(idf).Name,
**{
f"Layer_{i+2}": layer.to_epbunch(idf).Name
for i, layer in enumerate(self.Layers[1:])
},
)

The material name is for the IDF without differentiating by thickness:

Opaque Materials

if self._key == "MATERIAL:NOMASS":
# Special case for Material:NoMass
return idf.newidfobject(
"MATERIAL:NOMASS",
Name=self.Name,
Roughness=self.Roughness,
Thermal_Resistance=thickness / self.Conductivity,
Thermal_Absorptance=self.ThermalEmittance,
Solar_Absorptance=self.SolarAbsorptance,
Visible_Absorptance=self.VisibleAbsorptance,
)
elif self._key == "MATERIAL:AIRGAP":
return idf.newidfobject(
"MATERIAL:AIRGAP",
Name=self.Name,
Thermal_Resistance=thickness / self.Conductivity,
)
else:
return idf.newidfobject(
"MATERIAL",
Name=self.Name,
Roughness=self.Roughness,
Thickness=thickness,
Conductivity=self.Conductivity,
Density=self.Density,
Specific_Heat=self.SpecificHeat,
Thermal_Absorptance=self.ThermalEmittance,
Solar_Absorptance=self.SolarAbsorptance,
Visible_Absorptance=self.VisibleAbsorptance,
)

Glazing Materials

return idf.newidfobject(
"WINDOWMATERIAL:GLAZING",
Name=self.Name,
Optical_Data_Type="SpectralAverage",
Window_Glass_Spectral_Data_Set_Name="SpectralAverage",
Thickness=thickness,
Solar_Transmittance_at_Normal_Incidence=self.SolarTransmittance,
Front_Side_Solar_Reflectance_at_Normal_Incidence=self.SolarReflectanceFront,
Back_Side_Solar_Reflectance_at_Normal_Incidence=self.SolarReflectanceBack,
Visible_Transmittance_at_Normal_Incidence=self.VisibleTransmittance,
Front_Side_Visible_Reflectance_at_Normal_Incidence=self.VisibleReflectanceFront,
Back_Side_Visible_Reflectance_at_Normal_Incidence=self.VisibleReflectanceBack,
Infrared_Transmittance_at_Normal_Incidence=self.IRTransmittance,
Front_Side_Infrared_Hemispherical_Emissivity=self.IREmissivityFront,
Back_Side_Infrared_Hemispherical_Emissivity=self.IREmissivityBack,
Conductivity=self.Conductivity,
Dirt_Correction_Factor_for_Solar_and_Visible_Transmittance=self.DirtFactor,
)

Gas Materials

return idf.newidfobject(
"WINDOWMATERIAL:GAS",
Name=self.Name,
Gas_Type=self.Type,
Thickness=thickness,
)

Solution

Option 1

Probably the simplest and best approach is to add the thickness to the material name, e.g. Name=f"{self.Name}+{self.Thickness:0.4f}". This will mean each instance of a material with a given thickness gets its own entry in the IDF; constructions which have layers with identical material and thickness will still share the same material entry in the IDF. con is that the naming is a little ugly.

Option 2

Give the XMaterial.to_epbunch method an optional suffix argument. If provided, it gets added to the material's name when adding it to the IDF. The invoking Construction could pass in is name/id to the underlying material's to_epbunch as a suffix. Pro is that it makes the name is clearly traceable, but there are a few cons: doesn't actually fix the problem for constructions which use the same material twice but with different thicknesses (e.g. a double paned window with two separate gas layers). You could add the layer index to the suffix that is passed in to remedy this. Another con is that the IDF gets a lot heavier since even if two constructions have layers with the same material AND same thickness, they will still get separate entries. Another con is that a user who is directly calling the XMaterial.to_epbunch method may unintentionally overwrite another copy of the material with different thickness if they don't provide a suffix.

Option 3

Most rigorous, but also least performant. Within the XMaterial.to_epbunch method, check the IDF list of materials for instances of the same name (up to an integer suffix); if one with the same thickness exists, add with the same name including the suffix of the one found, thus overwriting the matching instance but no others (for instance if you were intentionally updating the material properties and did indeed want it to propagate). If you don't find any with matching thickness, add it to the IDF with a suffix which is the count of how many already exist in the same file with same name but different thickness.

Repro

material_epbunch_problem.ipynb.zip

@samuelduchesne samuelduchesne added the help wanted Extra attention is needed label Jul 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants