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

feat(writer): Add writer objects to go to.idf #36

Merged
merged 1 commit into from
Oct 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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'):
mostaphaRoudsari marked this conversation as resolved.
Show resolved Hide resolved
"""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)
chriswmackey marked this conversation as resolved.
Show resolved Hide resolved

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
13 changes: 10 additions & 3 deletions honeybee_energy/schedule/day.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,9 +425,16 @@ def from_dict(cls, data):

return cls(data['name'], data['values'], times, interpolate)

def to_idf(self):
"""IDF string representation of ScheduleDay object."""
fields = [self.name, '']
def to_idf(self, schedule_type_limit=None):
"""IDF string representation of ScheduleDay object.
chriswmackey marked this conversation as resolved.
Show resolved Hide resolved

Args:
schedule_type_limits: Optional ScheduleTypeLimit object, which will
be written into the IDFstring in order to validate the values
within the schedule during the EnergyPlus run.
"""
fields = [self.name, ''] if schedule_type_limit is None else \
[self.name, schedule_type_limit.name]
fields.append('No' if not self.interpolate else 'Linear')
comments = ['schedule name', 'schedule type limits', 'interpolate to timestep']
for i in range(len(self._values)):
Expand Down
10 changes: 8 additions & 2 deletions honeybee_energy/simulation/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,8 @@ def to_idf(self):
if no summary reports have not been requested.
sqlite: An IDF Output:SQLite string to request the SQLite file from
the simulation. Will be None if include_sqlite is False.
variable_dictionary: An IDF Output:VariableDictionary string, which
will ensure that a .rdd file is generated from the simulation.
surfaces_list: An IDF Output:Surfaces:List string to ensure surface
information is written into the ultimate .eio file.
"""
Expand All @@ -478,11 +480,15 @@ 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
variable_dictionary = generate_idf_string(
'Output:VariableDictionary', ('IDF', 'Unsorted'),
('key field', 'sort option'))
surfaces_list = generate_idf_string(
'Output:Surfaces:List', ('Details',), ('report type',))
return table_style, output_variables, summary_reports, sqlite, surfaces_list
return table_style, output_variables, summary_reports, sqlite, \
variable_dictionary, surfaces_list

def to_dict(self):
"""DaylightSavingTime dictionary representation."""
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
80 changes: 64 additions & 16 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,28 @@ 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.

Specifically, these are counter-clockwise vertices starting from the
upper left corner of the surface. The output string is the following:

.. code-block:: python

GlobalGeometryRules,
UpperLeftCorner, !- starting vertex position
Counterclockwise, !- vertex entry direction
Relative; !- coordinate system
"""
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 +192,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 +309,43 @@ def to_idf(self):
objects that make up the SimulationParameter (ie. RunPeriod, SimulationControl,
etc.),
"""
header_str = '!- ============== SIMULATION PARAMETERS ==============\n'
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 = ['!- ==========================================\n'
'!- ========= SIMULATION PARAMETERS =========\n'
'!- ==========================================\n']

# add the outputs requested
table_style, output_vars, reports, sqlite, rdd, surfaces = self.output.to_idf()
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(rdd)
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))
chriswmackey marked this conversation as resolved.
Show resolved Hide resolved
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 +363,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