Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
7081d54
add setters for simple umibase fields
szvsw Aug 13, 2022
b519530
enable linking
szvsw Aug 13, 2022
50f0aed
add parent template lookup based off of graph
szvsw Aug 13, 2022
233ca9f
implement umibaselist and unique_comps
szvsw Aug 13, 2022
6a0594b
fix UmiBaseList equality
szvsw Aug 14, 2022
7f8d51e
fix unlinking for template_addition
szvsw Aug 14, 2022
42e456d
add parent templates test
szvsw Aug 14, 2022
776ab1d
allow multiple umibaselists per umibase parent
szvsw Aug 14, 2022
bed6237
initialize umibase properties after basic properties
szvsw Aug 14, 2022
bd7011b
update graph method and fix iadd test fail
szvsw Aug 14, 2022
f9424b1
change ventilation initialization order
szvsw Aug 14, 2022
fe53cea
use predecessor to determine parents
szvsw Aug 14, 2022
15ae6df
fail silently if edge does not exist
szvsw Aug 14, 2022
f10bb7e
prevent validation error when creating ventilation
szvsw Aug 14, 2022
e4a030c
dont use pred in Parents
szvsw Aug 14, 2022
795551a
create replace component test
szvsw Aug 14, 2022
804c7e5
use fixture for template lib in test_umi
szvsw Aug 14, 2022
956bde4
create global graph
szvsw Aug 14, 2022
871a08c
create cleanup fixture
szvsw Aug 15, 2022
6d1a357
rewrite bt window loader for clarity
szvsw Aug 15, 2022
dc90457
make graph testing more rigorous
szvsw Aug 16, 2022
3ce74a3
enable logging
szvsw Aug 16, 2022
d1ff2d7
improve unique_components performance
szvsw Aug 16, 2022
dd5d80d
add cleanup pre testing
szvsw Aug 16, 2022
91508c9
add timeit to replace
szvsw Aug 16, 2022
3fa85e1
remove timeits
szvsw Aug 16, 2022
500d9e9
disable timeit
szvsw Aug 16, 2022
80db08a
skip replacing self
szvsw Aug 16, 2022
1cbb68a
add benchmark tests which skip by default
szvsw Aug 16, 2022
7f7b20c
rewrite benchmarks
szvsw Aug 16, 2022
e4c17cc
add extra items to benchmark for unique_comp
szvsw Aug 16, 2022
b4a5152
parametrize phantom object count
szvsw Aug 16, 2022
ed090ae
add benchmark logging
szvsw Aug 16, 2022
3f89938
skip benchmarks on ci
szvsw Aug 16, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions archetypal/schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -1572,7 +1572,7 @@ def _repr_svg_(self):
fig.savefig(f, format="svg")
return f.getvalue()

def combine(self, other, weights=None, quantity=None):
def combine(self, other, weights=None, quantity=None, **kwargs):
"""Combine two schedule objects together.

Args:
Expand Down Expand Up @@ -1614,7 +1614,7 @@ def combine(self, other, weights=None, quantity=None):
# the new object's name
name = "+".join([self.Name, other.Name])

new_obj = self.__class__(name, value=new_values)
new_obj = self.__class__(name, value=new_values, **kwargs)

return new_obj

Expand Down
70 changes: 43 additions & 27 deletions archetypal/template/building_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from archetypal.template.materials.material_layer import MaterialLayer
from archetypal.template.schedule import YearSchedulePart
from archetypal.template.structure import MassRatio, StructureInformation
from archetypal.template.umi_base import UmiBase
from archetypal.template.umi_base import UmiBase, umibase_property
from archetypal.template.window_setting import WindowSetting
from archetypal.template.zonedefinition import ZoneDefinition
from archetypal.utils import log, reduce
Expand All @@ -31,7 +31,6 @@ class BuildingTemplate(UmiBase):

.. image:: ../images/template/buildingtemplate.png
"""
_CREATED_OBJECTS = []

__slots__ = (
"_partition_ratio",
Expand Down Expand Up @@ -102,10 +101,6 @@ def __init__(
super(BuildingTemplate, self).__init__(Name, **kwargs)
self.PartitionRatio = PartitionRatio
self.Lifespan = Lifespan
self.Core = Core
self.Perimeter = Perimeter
self.Structure = Structure
self.Windows = Windows
self.DefaultWindowToWallRatio = DefaultWindowToWallRatio
self._year_from = YearFrom # set privately to allow validation
self.YearTo = YearTo
Expand All @@ -114,56 +109,49 @@ def __init__(
self.Authors = Authors if Authors else []
self.AuthorEmails = AuthorEmails if AuthorEmails else []
self.Version = Version
# Set UmiBase Properties after standard properties
self.Core = Core
self.Perimeter = Perimeter
self.Structure = Structure
self.Windows = Windows

# Only at the end append self to _CREATED_OBJECTS
self._CREATED_OBJECTS.append(self)

@property
@umibase_property(type_of_property=ZoneDefinition)
def Perimeter(self):
"""Get or set the perimeter ZoneDefinition."""
return self._perimeter

@Perimeter.setter
def Perimeter(self, value):
assert isinstance(
value, ZoneDefinition
), f"Expected a ZoneDefinition, not {type(value)}"
self._perimeter = value

@property
@umibase_property(type_of_property=ZoneDefinition)
def Core(self):
"""Get or set the core ZoneDefinition."""
return self._core

@Core.setter
def Core(self, value):
assert isinstance(
value, ZoneDefinition
), f"Expected a ZoneDefinition, not {type(value)}"
self._core = value

@property
@umibase_property(type_of_property=StructureInformation)
def Structure(self):
"""Get or set the StructureInformation."""
return self._structure_definition

@Structure.setter
def Structure(self, value):
assert isinstance(
value, StructureInformation
), f"Expected a StructureInformation, not {type(value)}"
self._structure_definition = value

@property
@umibase_property(type_of_property=WindowSetting)
def Windows(self):
"""Get or set the WindowSetting."""
return self._window_setting

@Windows.setter
def Windows(self, value):
assert isinstance(
value, WindowSetting
), f"Expected a WindowSetting, not {type(value)}"
self._window_setting = value

@property
Expand Down Expand Up @@ -332,12 +320,40 @@ def from_dict(
perim = zone_definitions[data.pop("Perimeter")["$ref"]]
structure = structure_definitions[data.pop("Structure")["$ref"]]
window_data = data.pop("Windows")

window = None
try:
window = window_settings[window_data["$ref"]]
window_ref = window_data["$ref"]
window = window_settings[window_ref]
except KeyError:
window = WindowSetting.from_dict(
window_data, schedules, window_constructions
)
try:
window = window_settings[window_data["$id"]]
except KeyError:
# If the window id changed because of preserve_ids, look for
# the matching window in window_settings
try:
window = next(
iter(
[
_window
for _window in window_settings.values()
if _window.id == window_data["$id"]
]
)
)
except StopIteration:
# then look in all objects
for obj in UmiBase.all_objects_of_type(WindowSetting):
if obj.id == window_data["$id"]:
obj_data = obj.to_dict()
if obj_data == window_data:
window = obj
break
# Create the window if it does not yet exist
if window is None:
window = WindowSetting.from_dict(
window_data, schedules, window_constructions
)

return cls(
Core=core,
Expand Down Expand Up @@ -623,7 +639,7 @@ def get_ref(self, ref):
iter(
[
value
for value in BuildingTemplate.CREATED_OBJECTS
for value in UmiBase.all_objects_of_type(BuildingTemplate)
if value.id == ref["$ref"]
]
),
Expand Down
36 changes: 11 additions & 25 deletions archetypal/template/conditioning.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from archetypal.reportdata import ReportData
from archetypal.template.schedule import UmiSchedule
from archetypal.template.umi_base import UmiBase
from archetypal.template.umi_base import UmiBase, umibase_property
from archetypal.utils import float_round, log


Expand Down Expand Up @@ -88,7 +88,6 @@ class ZoneConditioning(UmiBase):

.. image:: ../images/template/zoninfo-conditioning.png
"""
_CREATED_OBJECTS = []

__slots__ = (
"_cooling_setpoint",
Expand Down Expand Up @@ -259,9 +258,6 @@ def __init__(
:class:`archetypal.template.UmiBase`
"""
super(ZoneConditioning, self).__init__(Name, **kwargs)
self.MechVentSchedule = MechVentSchedule
self.HeatingSchedule = HeatingSchedule
self.CoolingSchedule = CoolingSchedule
self.CoolingCoeffOfPerf = CoolingCoeffOfPerf
self.CoolingLimitType = CoolingLimitType
self.CoolingFuelType = CoolingFuelType
Expand All @@ -286,6 +282,11 @@ def __init__(

self.area = area

# set UmiBase Properties after standard properties
self.MechVentSchedule = MechVentSchedule
self.HeatingSchedule = HeatingSchedule
self.CoolingSchedule = CoolingSchedule

# Only at the end append self to _CREATED_OBJECTS
self._CREATED_OBJECTS.append(self)

Expand Down Expand Up @@ -389,18 +390,13 @@ def IsHeatingOn(self, value):
)
self._is_heating_on = value

@property
@umibase_property(type_of_property=UmiSchedule)
def HeatingSchedule(self):
"""Get or set the heating availability schedule."""
return self._heating_schedule

@HeatingSchedule.setter
def HeatingSchedule(self, value):
if value is not None:
assert isinstance(value, UmiSchedule), (
f"Input error with value {value}. HeatingSchedule must "
f"be an UmiSchedule, not a {type(value)}"
)
self._heating_schedule = value

@property
Expand Down Expand Up @@ -469,18 +465,13 @@ def IsCoolingOn(self, value):
)
self._is_cooling_on = value

@property
@umibase_property(type_of_property=UmiSchedule)
def CoolingSchedule(self):
"""Get or set the cooling availability schedule."""
return self._cooling_schedule

@CoolingSchedule.setter
def CoolingSchedule(self, value):
if value is not None:
assert isinstance(value, UmiSchedule), (
f"Input error with value {value}. CoolingSchedule must "
f"be an UmiSchedule, not a {type(value)}"
)
self._cooling_schedule = value

@property
Expand Down Expand Up @@ -571,18 +562,13 @@ def EconomizerType(self, value):
elif isinstance(value, EconomizerTypes):
self._economizer_type = value

@property
@umibase_property(type_of_property=UmiSchedule)
def MechVentSchedule(self):
"""Get or set the outdoor air requirements over time."""
return self._mech_vent_schedule

@MechVentSchedule.setter
def MechVentSchedule(self, value):
if value is not None:
assert isinstance(value, UmiSchedule), (
f"Input error with value {value}. MechVentSchedule must "
f"be an UmiSchedule, not a {type(value)}"
)
self._mech_vent_schedule = value

@property
Expand Down Expand Up @@ -1390,7 +1376,7 @@ def _get_cop(zone, energy_in_list, energy_out_variable_name):

return cop

def combine(self, other, weights=None):
def combine(self, other, weights=None, **kwargs):
"""Combine two ZoneConditioning objects together.

Args:
Expand Down Expand Up @@ -1475,7 +1461,7 @@ def combine(self, other, weights=None):
)
# create a new object with the previous attributes
new_obj = self.__class__(
**meta, **new_attr, allow_duplicates=self.allow_duplicates
**meta, **new_attr, allow_duplicates=self.allow_duplicates, **kwargs
)
new_obj.predecessors.update(self.predecessors + other.predecessors)
return new_obj
Expand Down
16 changes: 11 additions & 5 deletions archetypal/template/constructions/base_construction.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from archetypal.template.materials import GasMaterial
from archetypal.template.materials.gas_layer import GasLayer
from archetypal.template.materials.material_layer import MaterialLayer
from archetypal.template.umi_base import UmiBase
from archetypal.template.umi_base import UmiBase, UmiBaseList


class ConstructionBase(UmiBase):
Expand Down Expand Up @@ -158,6 +158,7 @@ def __init__(self, Name, Layers, **kwargs):
constructor.
"""
super(LayeredConstruction, self).__init__(Name, **kwargs)
self._layers = UmiBaseList(self, "Layers")
self.Layers = Layers

@property
Expand All @@ -178,7 +179,7 @@ def Layers(self, value):
assert isinstance(
value[-1], MaterialLayer
), "The inside layer cannot be a GasLayer"
self._layers = value
self.Layers.relink_list(value)

@property
def r_value(self):
Expand Down Expand Up @@ -326,11 +327,16 @@ def __copy__(self):
"""Create a copy of self."""
return self.__class__(Name=self.Name, Layers=self.Layers)

def __hash__(self):
"""Return the hash value of self."""
return hash(self.id)

def __eq__(self, other):
"""Assert self is equivalent to other."""
return isinstance(other, LayeredConstruction) and all(
[self.Layers == other.Layers]
)
if not isinstance(other, LayeredConstruction):
return NotImplemented
else:
return all([self.Layers == other.Layers])

@property
def children(self):
Expand Down
6 changes: 2 additions & 4 deletions archetypal/template/constructions/opaque_construction.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ class OpaqueConstruction(LayeredConstruction):
* solar_reflectance_index
"""

_CREATED_OBJECTS = []

__slots__ = ("area",)

def __init__(self, Name, Layers, **kwargs):
Expand Down Expand Up @@ -167,7 +165,7 @@ def infer_insulation_layer(self):
"""Return the material layer index that corresponds to the insulation layer."""
return self.Layers.index(max(self.Layers, key=lambda x: x.r_value))

def combine(self, other, method="dominant_wall", allow_duplicates=False):
def combine(self, other, method="dominant_wall", allow_duplicates=False, **kwargs):
"""Combine two OpaqueConstruction together.

Args:
Expand Down Expand Up @@ -217,7 +215,7 @@ def combine(self, other, method="dominant_wall", allow_duplicates=False):
)
# layers for the new OpaqueConstruction
layers = [MaterialLayer(mat, t) for mat, t in zip(new_m, new_t)]
new_obj = self.__class__(**meta, Layers=layers)
new_obj = self.__class__(**meta, Layers=layers, **kwargs)
new_name = (
"Combined Opaque Construction {{{}}} with u_value "
"of {:,.3f} W/m2k".format(uuid.uuid1(), new_obj.u_value)
Expand Down
4 changes: 1 addition & 3 deletions archetypal/template/constructions/window_construction.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ class WindowConstruction(LayeredConstruction):
.. image:: ../images/template/constructions-window.png
"""

_CREATED_OBJECTS = []

_CATEGORIES = ("single", "double", "triple", "quadruple")

__slots__ = ("_category",)
Expand Down Expand Up @@ -360,7 +358,7 @@ def mapping(self, validate=False):
Name=self.Name,
)

def combine(self, other, weights=None):
def combine(self, other, weights=None, **kwargs):
"""Append other to self. Return self + other as a new object.

For now, simply returns self.
Expand Down
Loading