Skip to content

Commit

Permalink
feat(writer): Add writer objects to go to.idf
Browse files Browse the repository at this point in the history
Working with the new structure of honeybee-core writers. This commit officially brings everything together to make a simulate-able IDF!
  • Loading branch information
chriswmackey committed Oct 18, 2019
1 parent 1fd3a8f commit 34aefa8
Show file tree
Hide file tree
Showing 11 changed files with 590 additions and 52 deletions.
19 changes: 15 additions & 4 deletions honeybee_energy/_extend_honeybee.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
# coding=utf-8
from honeybee.properties import ModelProperties, RoomProperties, FaceProperties, \
ShadeProperties, ApertureProperties, DoorProperties
import honeybee.writer as writer
import honeybee.writer.door as door_writer
import honeybee.writer.aperture as aperture_writer
import honeybee.writer.shade as shade_writer
import honeybee.writer.face as face_writer
import honeybee.writer.room as room_writer
import honeybee.writer.model as model_writer
import honeybee.boundarycondition as hbc

from .properties.model import ModelEnergyProperties
Expand All @@ -10,11 +15,12 @@
from .properties.shade import ShadeEnergyProperties
from .properties.aperture import ApertureEnergyProperties
from .properties.door import DoorEnergyProperties
from .writer import face_to_idf
from .writer import model_to_idf, room_to_idf, face_to_idf, shade_to_idf, \
aperture_to_idf, door_to_idf
from .boundarycondition import Adiabatic

# set a hidden energy attribute on each core geometry Property class to None
# define methods to produce energy property instances on each Proprety instance
# define methods to produce energy property instances on each Property instance
ModelProperties._energy = None
RoomProperties._energy = None
FaceProperties._energy = None
Expand Down Expand Up @@ -68,7 +74,12 @@ def door_energy_properties(self):
DoorProperties.energy = property(door_energy_properties)

# add energy writer to idf
setattr(writer, 'idf', face_to_idf)
model_writer.idf = model_to_idf
room_writer.idf = room_to_idf
face_writer.idf = face_to_idf
shade_writer.idf = shade_to_idf
aperture_writer.idf = aperture_to_idf
door_writer.idf = door_to_idf

# extend boundary conditions
setattr(hbc, 'Adiabatic', Adiabatic)
Expand Down
28 changes: 28 additions & 0 deletions honeybee_energy/properties/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from ..schedule.typelimit import ScheduleTypeLimit
from ..schedule.ruleset import ScheduleRuleset
from ..schedule.fixedinterval import ScheduleFixedInterval
from ..writer import generate_idf_string

try:
from itertools import izip as zip # python 2
Expand Down Expand Up @@ -261,6 +262,33 @@ def program_types(self):
program_types.append(room.properties.energy._program_type)
return list(set(program_types)) # catch equivalent program types

def building_idf(self, solar_distribution='FullInteriorAndExteriorWithReflections'):
"""Get an IDF string for Building that this model represents.
Args:
solar_distribution: Text desribing how EnergyPlus should treat beam solar
radiation reflected from surfaces. Default:
FullInteriorAndExteriorWithReflections. Choose from the following:
* MinimalShadowing
* FullExterior
* FullInteriorAndExterior
* FullExteriorWithReflections
* FullInteriorAndExteriorWithReflections
"""
values = (self.host.name,
self.host.north_angle,
self.terrain_type,
'',
'',
solar_distribution)
comments = ('name',
'north axis',
'terrain',
'loads convergence tolerance',
'temperature convergence tolerance',
'solar distribution')
return generate_idf_string('Building', values, comments)

def check_duplicate_material_names(self, raise_exception=True):
"""Check that there are no duplicate Material names in the model."""
material_names = set()
Expand Down
2 changes: 1 addition & 1 deletion honeybee_energy/simulation/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ def to_idf(self):
'Output:Table:SummaryReports', self.summary_reports, r_comments) if \
len(self._summary_reports) != 0 else None
sqlite = generate_idf_string(
'Output:SQLite', ('SimpleAndTabular,'), ('option type',)) if \
'Output:SQLite', ('SimpleAndTabular',), ('option type',)) if \
self.include_sqlite else None
surfaces_list = generate_idf_string(
'Output:Surfaces:List', ('Details',), ('report type',))
Expand Down
6 changes: 3 additions & 3 deletions honeybee_energy/simulation/sizing.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ def from_idf(cls, idf_string):
Args:
idf_string: A text string fully describing an EnergyPlus
SizingParameters definition.
Sizing:Parameters definition.
"""
# check the inputs
ep_strs = parse_idf_string(idf_string, 'SizingParameters,')
ep_strs = parse_idf_string(idf_string, 'Sizing:Parameters,')

# extract the properties from the string
heating_factor = 1.25
Expand Down Expand Up @@ -99,7 +99,7 @@ def to_idf(self):
"""Get an EnergyPlus string representation of the SizingParameters."""
values = (self.heating_factor, self.cooling_factor)
comments = ('heating factor', 'cooling factor')
return generate_idf_string('SizingParameters', values, comments)
return generate_idf_string('Sizing:Parameters', values, comments)

def to_dict(self):
"""SizingParameter dictionary representation."""
Expand Down
66 changes: 51 additions & 15 deletions honeybee_energy/simulationparameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class SimulationParameter(object):
* simulation_control
* shadow_calculation
* sizing_parameter
* global_geometry_rules
"""
__slots__ = ('_output', '_run_period', '_timestep', '_simulation_control',
'_shadow_calculation', '_sizing_parameter')
Expand Down Expand Up @@ -144,6 +145,17 @@ def sizing_parameter(self, value):
else:
self._sizing_parameter = SizingParameter()

@property
def global_geometry_rules(self):
"""Get an IDF string for the official honeybee global geometry rules."""
values = ('UpperLeftCorner',
'Counterclockwise',
'Relative')
comments = ('starting vertex position',
'vertex entry direction',
'coordinate system')
return generate_idf_string('GlobalGeometryRules', values, comments)

@classmethod
def from_idf(cls, idf_string):
"""Create a SimulationParameter object from an EnergyPlus IDF text string.
Expand All @@ -169,7 +181,7 @@ def from_idf(cls, idf_string):
sh_calc_pattern = re.compile(r"(?i)(ShadowCalculation,[\s\S]*?;)")
bldg_pattern = re.compile(r"(?i)(Building,[\s\S]*?;)")
control_pattern = re.compile(r"(?i)(SimulationControl,[\s\S]*?;)")
sizing_pattern = re.compile(r"(?i)(SizingParameters,[\s\S]*?;)")
sizing_pattern = re.compile(r"(?i)(Sizing:Parameters,[\s\S]*?;)")

# process the outputs within the idf_string
try:
Expand Down Expand Up @@ -286,22 +298,42 @@ def to_idf(self):
objects that make up the SimulationParameter (ie. RunPeriod, SimulationControl,
etc.),
"""
header_str = '!- ============== SIMULATION PARAMETERS ==============\n'
sim_param_str = ['!- ==========================================\n'
'!- ========= SIMULATION PARAMETERS =========\n'
'!- ==========================================\n']

# add the outputs requested
table_style, output_vars, reports, sqlite, surfaces = self.output.to_idf()
output_vars_str = '/n/n'.join(output_vars) if output_vars is not None else ''
sim_param_str.append(table_style)
if output_vars is not None:
sim_param_str.append('\n\n'.join(output_vars))
if reports is not None:
sim_param_str.append(reports)
if sqlite is not None:
sim_param_str.append(sqlite)
sim_param_str.append(surfaces)

# add simulation settings
sim_param_str.append(self.simulation_control.to_idf())
sim_param_str.append(self.shadow_calculation.to_idf())
sim_param_str.append(generate_idf_string(
'Timestep', [self.timestep], ['timesteps per hour']))

# add the run period
run_period_str, holidays, daylight_saving = self.run_period.to_idf()
holiday_str = '/n/n'.join(holidays) if holidays is not None else ''
daylight_saving_time_str = daylight_saving if daylight_saving is not None else ''
timestep_str = generate_idf_string(
'Timestep', [self.timestep], ['timesteps per hour'])
sim_control_str = self.simulation_control.to_idf()
shadow_calc_str = self.shadow_calculation.to_idf()
sizing_par_str = self.sizing_parameter.to_idf()

return '/n/n'.join([table_style, output_vars_str, reports, sqlite, surfaces,
header_str, sim_control_str, shadow_calc_str, timestep_str,
run_period_str, holiday_str, daylight_saving_time_str,
sizing_par_str])
sim_param_str.append(run_period_str)
if holidays is not None:
sim_param_str.append('\n\n'.join(holidays))
if daylight_saving is not None:
sim_param_str.append(daylight_saving)

# write the sizing parameters
sim_param_str.append(self.sizing_parameter.to_idf())

# write the global geometry rules
sim_param_str.append(self.global_geometry_rules)

return '\n\n'.join(sim_param_str)

def to_dict(self):
"""SimulationParameter dictionary representation."""
Expand All @@ -319,6 +351,10 @@ def duplicate(self):
"""Get a copy of this object."""
return self.__copy__()

def ToString(self):
"""Overwrite .NET ToString."""
return self.__repr__()

def __copy__(self):
return SimulationParameter(
self.output.duplicate(), self.run_period.duplicate(), self.timestep,
Expand Down
Loading

0 comments on commit 34aefa8

Please sign in to comment.