Class: BuildingSync::Facility

Inherits:
Object
  • Object
show all
Includes:
Helper, XmlGetSet, OsLib_Geometry
Defined in:
lib/buildingsync/model_articulation/facility.rb

Overview

Facility class

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from XmlGetSet

#get_prefix, #xget_attribute_for_element, #xget_element, #xget_id, #xget_idrefs, #xget_linked_premises, #xget_name, #xget_or_create, #xget_plurals_text_value, #xget_text, #xget_text_as_bool, #xget_text_as_date, #xget_text_as_dt, #xget_text_as_float, #xget_text_as_integer, #xset_or_create, #xset_text

Methods included from Helper

#help_calculate_hours, #help_convert, #help_count_number_of_days, #help_element_class_type_check, #help_get_attribute_value, #help_get_default_schedule_set, #help_get_duration, #help_get_end_time, #help_get_end_time_sat, #help_get_end_time_sun, #help_get_end_time_weekday, #help_get_or_create, #help_get_schedule_rule_set_from_schedule, #help_get_start_time, #help_get_start_time_sat, #help_get_start_time_sun, #help_get_start_time_weekday, #help_get_text_value, #help_get_text_value_as_bool, #help_get_text_value_as_date, #help_get_text_value_as_datetime, #help_get_text_value_as_float, #help_get_text_value_as_integer, #help_get_zone_name_list, #help_load_doc, #help_print_all_schedules, #help_print_schedule, #help_write_profile

Constructor Details

#initialize(base_xml, ns) ⇒ Facility

initialize

Parameters:

  • base_xml (REXML:Element)
  • ns (String)


64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/buildingsync/model_articulation/facility.rb', line 64

def initialize(base_xml, ns)
  @base_xml = base_xml
  @ns = ns
  @g = BuildingSync::Generator.new(ns)

  help_element_class_type_check(base_xml, 'Facility')

  @report_xml = nil
  @site_xml = nil

  @site = nil
  @report = nil

  @measures = []
  @contacts = []
  @systems_map = {}

  # TODO: Go under Report
  @utility_name = nil
  @utility_meter_numbers = []
  @metering_configuration = nil
  @spaces_excluded_from_gross_floor_area = nil

  @load_system = nil
  @hvac_system = nil

  # reading the xml
  read_xml
end

Instance Attribute Details

#contactsObject (readonly)

Returns the value of attribute contacts.



437
438
439
# File 'lib/buildingsync/model_articulation/facility.rb', line 437

def contacts
  @contacts
end

#measuresObject (readonly)

Returns the value of attribute measures.



437
438
439
# File 'lib/buildingsync/model_articulation/facility.rb', line 437

def measures
  @measures
end

#reportObject (readonly)

Returns the value of attribute report.



437
438
439
# File 'lib/buildingsync/model_articulation/facility.rb', line 437

def report
  @report
end

#siteObject (readonly)

Returns the value of attribute site.



437
438
439
# File 'lib/buildingsync/model_articulation/facility.rb', line 437

def site
  @site
end

#systems_mapObject (readonly)

Returns the value of attribute systems_map.



437
438
439
# File 'lib/buildingsync/model_articulation/facility.rb', line 437

def systems_map
  @systems_map
end

Instance Method Details

#add_blank_lighting_system(premise_id, premise_type, lighting_system_id = 'LightingSystem-1') ⇒ BuildingSync::LightingSystemType

Add a minimal lighting system in the doc and as an object

Parameters:

  • premise_id (String)

    id of the premise which the system will be linked to

  • premise_type (String)

    type of premise, i.e. Building, Section, etc.

  • lighting_system_id (String) (defaults to: 'LightingSystem-1')

    id for new lighting system

Returns:



245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/buildingsync/model_articulation/facility.rb', line 245

def add_blank_lighting_system(premise_id, premise_type, lighting_system_id = 'LightingSystem-1')
  # Create new lighting system and link it
  lighting_system_xml = @g.add_lighting_system_to_facility(@base_xml, lighting_system_id)
  @g.add_linked_premise(lighting_system_xml, premise_id, premise_type)

  # Create a new array if doesn't yet exist
  if !@systems_map.key?('LightingSystems')
    @systems_map['LightingSystems'] = []
  end

  # Create new lighting system and add to array
  new_system = BuildingSync::LightingSystemType.new(lighting_system_xml, @ns)
  @systems_map['LightingSystems'] << new_system
  return new_system
end

#add_cb_modeled(id = 'Scenario-Baseline') ⇒ Object

See Also:

  • Report.add_cb_modeled


236
237
238
# File 'lib/buildingsync/model_articulation/facility.rb', line 236

def add_cb_modeled(id = 'Scenario-Baseline')
  @report.add_cb_modeled(id)
end

#build_zone_hash(site) ⇒ Hash

build zone hash

Parameters:

Returns:

  • (Hash)


170
171
172
# File 'lib/buildingsync/model_articulation/facility.rb', line 170

def build_zone_hash(site)
  return site.build_zone_hash
end

#create_building_systems(main_output_dir:, zone_hash: nil, hvac_delivery_type: 'Forced Air', htg_src: 'NaturalGas', clg_src: 'Electricity', add_space_type_loads: true, add_constructions: true, add_elevators: false, add_exterior_lights: false, add_exhaust: true, add_swh: true, add_hvac: true, add_thermostat: true, remove_objects: false) ⇒ Object

create building systems

Parameters:

  • main_output_dir (String)

    main output path, not scenario specific. i.e. SR should be a subdirectory

  • zone_hash (Hash) (defaults to: nil)
  • hvac_delivery_type (String) (defaults to: 'Forced Air')
  • htg_src (String) (defaults to: 'NaturalGas')
  • clg_src (String) (defaults to: 'Electricity')
  • add_space_type_loads (Boolean) (defaults to: true)
  • add_constructions (Boolean) (defaults to: true)
  • add_elevators (Boolean) (defaults to: false)
  • add_exterior_lights (Boolean) (defaults to: false)
  • add_exhaust (Boolean) (defaults to: true)
  • add_swh (Boolean) (defaults to: true)
  • add_hvac (Boolean) (defaults to: true)
  • add_thermostat (Boolean) (defaults to: true)
  • remove_objects (Boolean) (defaults to: false)


288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
# File 'lib/buildingsync/model_articulation/facility.rb', line 288

def create_building_systems(main_output_dir:, zone_hash: nil, hvac_delivery_type: 'Forced Air', htg_src: 'NaturalGas', clg_src: 'Electricity',
                            add_space_type_loads: true, add_constructions: true, add_elevators: false, add_exterior_lights: false,
                            add_exhaust: true, add_swh: true, add_hvac: true, add_thermostat: true, remove_objects: false)
  model = @site.get_model
  template = @site.get_standard_template
  system_type = @site.get_system_type
  climate_zone = @site.get_climate_zone

  onsite_parking_fraction = 1.0
  exterior_lighting_zone = '3 - All Other Areas'

  initial_objects = model.getModelObjects.size

  OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.Facility.create_building_system', "The building started with #{initial_objects} objects.")
  puts "BuildingSync.Facility.create_building_system - The building started with #{initial_objects} objects."

  # TODO: systems_xml.elements["#{@ns}:LightingSystems"]
  # Make the open_studio_system_standard applier
  open_studio_system_standard = determine_open_studio_system_standard
  OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.Facility.create_building_system', "Building Standard with template: #{template}.")

  # add internal loads to space types
  if add_space_type_loads
    @load_system.add_internal_loads(model, open_studio_system_standard, template, @site.get_building_sections, remove_objects)
    new_occupancy_peak = @site.get_peak_occupancy
    new_occupancy_peak.each do |id, occupancy_peak|
      floor_area = @site.get_floor_area[id]
      if occupancy_peak && floor_area && floor_area > 0.0
        puts "new peak occupancy value found: absolute occupancy: #{occupancy_peak} occupancy per area: #{occupancy_peak.to_f / floor_area.to_f} and area: #{floor_area} m2"
        @load_system.adjust_occupancy_peak(model, occupancy_peak, floor_area, @site.get_space_types_from_hash(id))
      end
    end
  end

  # identify primary building type (used for construction, and ideally HVAC as well)
  building_types = {}
  model.getSpaceTypes.each do |space_type|
    # populate hash of building types
    if space_type.standardsBuildingType.is_initialized
      bldg_type = space_type.standardsBuildingType.get
      if !building_types.key?(bldg_type)
        building_types[bldg_type] = space_type.floorArea
      else
        building_types[bldg_type] += space_type.floorArea
      end
    else
      OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.Facility.create_building_system', "Can't identify building type for #{space_type.name}")
    end
  end
  primary_bldg_type = building_types.key(building_types.values.max) # TODO: - this fails if no space types, or maybe just no space types with standards
  lookup_building_type = open_studio_system_standard.model_get_lookup_name(primary_bldg_type) # Used for some lookups in the standards gem
  model.getBuilding.setStandardsBuildingType(primary_bldg_type)

  envelope_system = nil
  # make construction set and apply to building
  if add_constructions
    envelope_system = EnvelopeSystem.new
    envelope_system.create(model, open_studio_system_standard, primary_bldg_type, lookup_building_type, remove_objects)
  end

  # add elevators (returns ElectricEquipment object)
  if add_elevators
    @load_system.add_elevator(model, open_studio_system_standard)
  end

  # add exterior lights (returns a hash where key is lighting type and value is exteriorLights object)
  if add_exterior_lights
    if !@systems_map['LightingSystems'].nil?
      @systems_map['LightingSystems'].each do |lighting_system|
        lighting_system.add_exterior_lights(model, open_studio_system_standard, onsite_parking_fraction, exterior_lighting_zone, remove_objects)
      end
    else
      new_lighting_system = add_blank_lighting_system(@site.get_building.xget_id, 'Building')
      new_lighting_system.add_exterior_lights(model, open_studio_system_standard, onsite_parking_fraction, exterior_lighting_zone, remove_objects)
    end
  end

  # add_exhaust
  if add_exhaust
    @hvac_system.add_exhaust(model, open_studio_system_standard, 'Adjacent', remove_objects)
  end

  # add service water heating demand and supply
  if add_swh
    service_hot_water_system = ServiceHotWaterSystem.new
    service_hot_water_system.add(model, open_studio_system_standard, remove_objects)
  end

  # TODO: Make this better
  @lighting_system.add_daylighting_controls(model, open_studio_system_standard, template, main_output_dir)

  # TODO: - add internal mass
  # TODO: - add slab modeling and slab insulation
  # TODO: - fuel customization for cooking and laundry
  # TODO: - add refrigeration
  # remove refrigeration equipment
  if remove_objects
    model.getRefrigerationSystems.each(&:remove)
  end

  # works by switching some fraction of electric loads to gas if requested (assuming base load is electric)
  # add thermostats
  if add_thermostat
    @hvac_system.add_thermostats(model, open_studio_system_standard, remove_objects)
  end

  # add hvac system
  if add_hvac
    @hvac_system.add_hvac(model, zone_hash, open_studio_system_standard, system_type, hvac_delivery_type, htg_src, clg_src, remove_objects)
  end

  # set hvac controls and efficiencies (this should be last model articulation element)
  if add_hvac
    if remove_objects
      model.purgeUnusedResourceObjects
      objects_after_cleanup = initial_objects - model.getModelObjects.size
      OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.Facility.create_building_system', "Removing #{objects_after_cleanup} objects from model")
    end
    @hvac_system.apply_sizing_and_assumptions(model, main_output_dir, open_studio_system_standard, primary_bldg_type, system_type, climate_zone)
  end

  # remove everything but spaces, zones, and stub space types (extend as needed for additional objects, may make bool arg for this)
  if remove_objects
    model.purgeUnusedResourceObjects
    objects_after_cleanup = initial_objects - model.getModelObjects.size
    if objects_after_cleanup > 0
      OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.Facility.create_building_system', "Removing #{objects_after_cleanup} objects from model")
    end
  end

  # report final condition of model
  OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.Facility.create_building_system', "The building finished with #{model.getModelObjects.size} objects.")
  puts "BuildingSync.Facility.create_building_system - The building finished with #{model.getModelObjects.size} objects."
end

#determine_open_studio_standard(standard_to_be_used) ⇒ Standard

determine open studio standard

Parameters:

  • standard_to_be_used (String)

Returns:

  • (Standard)


148
149
150
# File 'lib/buildingsync/model_articulation/facility.rb', line 148

def determine_open_studio_standard(standard_to_be_used)
  return @site.determine_open_studio_standard(standard_to_be_used)
end

#determine_open_studio_system_standardStandard

determine OpenStudio system standard

Returns:

  • (Standard)


206
207
208
# File 'lib/buildingsync/model_articulation/facility.rb', line 206

def determine_open_studio_system_standard
  return @site.determine_open_studio_system_standard
end

#generate_baseline_osm(epw_file_path, output_path, standard_to_be_used, ddy_file = nil) ⇒ Boolean

generating the OpenStudio model based on the imported BuildingSync Data

Parameters:

  • epw_file_path (String)
  • output_path (String)
  • standard_to_be_used (String)
  • ddy_file (String) (defaults to: nil)

Returns:

  • (Boolean)


158
159
160
161
162
163
164
165
# File 'lib/buildingsync/model_articulation/facility.rb', line 158

def generate_baseline_osm(epw_file_path, output_path, standard_to_be_used, ddy_file = nil)
  @site.generate_baseline_osm(epw_file_path, standard_to_be_used, ddy_file)

  @epw_file_path = @site.get_epw_file_path
  zone_hash = build_zone_hash(@site)
  create_building_systems(main_output_dir: output_path, zone_hash: zone_hash, remove_objects: true)
  return true
end

#get_auditor_contact_nameString?

Get the ContactName specified by the AuditorContactID/@IDref

Returns:

  • (String)

    if exists

  • (nil)

    if not



189
190
191
192
193
194
195
196
# File 'lib/buildingsync/model_articulation/facility.rb', line 189

def get_auditor_contact_name
  auditor_id = @report.get_auditor_contact_id
  if !auditor_id.nil?
    contact = @contacts.find { |contact| contact.xget_id == auditor_id }
    return contact.xget_text('ContactName')
  end
  return nil
end

#get_epw_file_pathString

get epw_file_path

Returns:

  • (String)


182
183
184
# File 'lib/buildingsync/model_articulation/facility.rb', line 182

def get_epw_file_path
  @site.get_epw_file_path
end

#get_modelOpenStudio::Model

get OpenStudio model

Returns:

  • (OpenStudio::Model)


200
201
202
# File 'lib/buildingsync/model_articulation/facility.rb', line 200

def get_model
  return @site.get_model
end

#get_space_typesArray<OpenStudio::Model::SpaceType>

get space types

Returns:

  • (Array<OpenStudio::Model::SpaceType>)


176
177
178
# File 'lib/buildingsync/model_articulation/facility.rb', line 176

def get_space_types
  return @site.get_space_types
end

#prepare_final_xmlObject

TODO: I don’t think we want any of this. write parameters to xml



433
434
435
# File 'lib/buildingsync/model_articulation/facility.rb', line 433

def prepare_final_xml
  @site.prepare_final_xml
end

#read_and_create_initial_systemsObject

read systems



211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/buildingsync/model_articulation/facility.rb', line 211

def read_and_create_initial_systems
  systems_xml = xget_or_create('Systems')
  if !systems_xml.elements.empty?
    systems_xml.elements.each do |system_type|
      @systems_map[system_type.name] = []
      system_type.elements.each do |system_xml|
        if system_xml.name == 'HVACSystem'
          @systems_map[system_type.name] << BuildingSync::HVACSystem.new(system_xml, @ns)
        elsif system_xml.name == 'LightingSystem'
          @systems_map[system_type.name] << BuildingSync::LightingSystemType.new(system_xml, @ns)
        else
          @systems_map[system_type.name] << system_xml
        end
      end
    end
  else
    hvac_xml = @g.add_hvac_system_to_facility(@base_xml)
    lighting_xml = @g.add_lighting_system_to_facility(@base_xml)
    @hvac_system = HVACSystem.new(hvac_xml, @ns)
    @lighting_system = LightingSystemType.new(lighting_xml, @ns)
    @load_system = LoadsSystem.new
  end
end

#read_other_detailsObject

read other details from the xml

  • contact information

  • audit levels and dates

  • Utility information

  • UDFs



266
267
268
269
270
271
# File 'lib/buildingsync/model_articulation/facility.rb', line 266

def read_other_details
  # Get Contact information
  @base_xml.elements.each("#{@ns}:Contacts/#{@ns}:Contact") do |contact|
    @contacts << BuildingSync::Contact.new(contact, @ns)
  end
end

#read_xmlObject

read xml



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/buildingsync/model_articulation/facility.rb', line 95

def read_xml
  # Site - checks
  site_xml_temp = @base_xml.get_elements("#{@ns}:Sites/#{@ns}:Site")
  if site_xml_temp.nil? || site_xml_temp.empty?
    OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Facility.read_xml', "Facility ID: #{xget_id} has no Site elements.  Cannot initialize Facility.")
    raise StandardError, "Facility with ID: #{xget_id} has no Site elements.  Cannot initialize Facility."
  elsif site_xml_temp.size > 1
    @site_xml = site_xml_temp.first
    OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Facility.read_xml', "Facility ID: #{xget_id}. There is more than one (#{site_xml_temp.size}) Site elements. Only the first Site will be considered (ID: #{@site_xml.attributes['ID']}")
  else
    @site_xml = site_xml_temp.first
  end
  # Create new Site
  @site = BuildingSync::Site.new(@site_xml, @ns)

  # Report - checks
  report_xml_temp = @base_xml.get_elements("#{@ns}:Reports/#{@ns}:Report")
  if report_xml_temp.nil? || report_xml_temp.empty?
    OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Facility.read_xml', "Facility with ID: #{xget_id} has no Report elements.  Cannot initialize Facility.")
    raise StandardError, "Facility with ID: #{xget_id} has no Report elements.  Cannot initialize Facility."
  elsif report_xml_temp.size > 1
    @report_xml = report_xml_temp.first
    OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.Facility.read_xml', "There are more than one (#{report_xml_temp.size}) Report elements in your BuildingSync file. Only the first Report will be considered (ID: #{@report_xml.attributes['ID']}")
  else
    @report_xml = report_xml_temp.first
  end
  # Create new Report
  @report = BuildingSync::Report.new(@report_xml, @ns)

  measures_xml_temp = @base_xml.get_elements("#{@ns}:Measures/#{@ns}:Measure")

  # Measures - create
  if !measures_xml_temp.nil?
    measures_xml_temp.each do |measure_xml|
      if measure_xml.is_a? REXML::Element
        @measures.push(BuildingSync::Measure.new(measure_xml, @ns))
      end
    end
    OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.Facility.read_xml', "Facility with ID: #{xget_id} has #{@measures.size} Measure Objects")
  end

  read_other_details
  read_and_create_initial_systems
end

#set_allObject

set_all wrapper for Site



141
142
143
# File 'lib/buildingsync/model_articulation/facility.rb', line 141

def set_all
  @site.set_all
end

#write_osm(dir) ⇒ Array

write osm

Parameters:

  • dir (String)

Returns:

  • (Array)


426
427
428
429
# File 'lib/buildingsync/model_articulation/facility.rb', line 426

def write_osm(dir)
  scenario_types = @site.write_osm(dir)
  return scenario_types
end