Module: OsLib_Cofee

Defined in:
lib/measures/SimplifyGeometryToSlicedBar/resources/os_lib_cofee.rb

Overview

******************************************************************************* OpenStudio®, Copyright © Alliance for Sustainable Energy, LLC. See also openstudio.net/license *******************************************************************************

Class Method Summary collapse

Class Method Details

.createBar(model, spaceTypeHash, lengthXTarget, lengthYTarget, totalFloorArea, numStories, midFloorMultiplier, xmin, ymin, lengthX, lengthY, zmin, zmax, endZones) ⇒ Object

create def to use later to make bar



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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
93
94
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/measures/SimplifyGeometryToSlicedBar/resources/os_lib_cofee.rb', line 8

def self.createBar(model, spaceTypeHash, lengthXTarget, lengthYTarget, totalFloorArea, numStories, midFloorMultiplier, xmin, ymin, lengthX, lengthY, zmin, zmax, endZones)
  # floor to floor height
  floor_to_floor_height = (zmax - zmin) / numStories

  # perimeter depth
  perimeterDepth = OpenStudio.convert(12, 'ft', 'm').get
  perimeterBufferFactor = 1.5 # this is a margin below which I won't bother splitting the two largest spaces

  # create an array to control sort order of spaces in bar
  customSpaceTypeBar = []
  counter = 0
  spaceTypeHash.sort_by { |key, value| value }.reverse_each do |k, v|
    next if v == 0 # this line adds support for fractional values of 0

    if counter == 1
      if (lengthXTarget * (v / totalFloorArea) > perimeterDepth * perimeterBufferFactor) && endZones
        customSpaceTypeBar << [k, totalFloorArea * (perimeterDepth / lengthXTarget)]
        customSpaceTypeBar << [k, v - (totalFloorArea * (perimeterDepth / lengthXTarget))]
      else
        customSpaceTypeBar << [k, v]
      end
    elsif counter > 1
      customSpaceTypeBar << [k, v]
    end
    counter += 1
  end

  # add the largest space type to the end
  counter = 0
  spaceTypeHash.sort_by { |key, value| value }.reverse_each do |k, v|
    if counter == 0
      # if width is greater than 1.5x perimeter depth then split in half
      if (lengthXTarget * (v / totalFloorArea) > perimeterDepth * perimeterBufferFactor) && endZones
        customSpaceTypeBar << [k, v - (totalFloorArea * (perimeterDepth / lengthXTarget))]
        customSpaceTypeBar << [k, totalFloorArea * (perimeterDepth / lengthXTarget)]
      else
        customSpaceTypeBar << [k, v]
      end
    end
    break
  end

  # starting z level
  z = zmin
  storyCounter = 0
  barSpaceArray = []

  # create new stories and then add spaces
  [numStories, 3].min.times do # no more than tree loops through this
    story = OpenStudio::Model::BuildingStory.new(model)
    story.setNominalFloortoFloorHeight(floor_to_floor_height)
    story.setNominalZCoordinate(z)

    # starting position for first space
    x = (lengthX - lengthXTarget) * 0.5 + xmin
    y = (lengthY - lengthYTarget) * 0.5 + ymin

    # temp array of spaces (this is to change floor boundary when there is mid floor multiplier)
    tempSpaceArray = []

    # loop through space types making diagram and spaces.
    # spaceTypeHash.sort_by {|key, value| value}.reverse.each do |k,v|
    customSpaceTypeBar.each do |object|
      # get values from what was hash
      k = object[0]
      v = object[1]

      # get proper zone multiplier value
      if (storyCounter == 1) && (midFloorMultiplier > 1)
        thermalZoneMultiplier = midFloorMultiplier
      else
        thermalZoneMultiplier = 1
      end

      options = {
        'name' => nil,
        'spaceType' => k,
        'story' => story,
        'make_thermal_zone' => true,
        'thermal_zone' => nil,
        'thermal_zone_multiplier' => thermalZoneMultiplier,
        'floor_to_floor_height' => floor_to_floor_height
      }

      # three paths for spaces depending upon building depth (3, 2 or one cross slices)
      if lengthYTarget > perimeterDepth * 3 # slice into core and perimeter

        # perimeter polygon a
        perim_polygon_a = OpenStudio::Point3dVector.new
        perim_origin_a = OpenStudio::Point3d.new(x, y, z)
        perim_polygon_a << perim_origin_a
        perim_polygon_a << OpenStudio::Point3d.new(x, y + perimeterDepth, z)
        perim_polygon_a << OpenStudio::Point3d.new(x + lengthXTarget * (v / totalFloorArea), y + perimeterDepth, z)
        perim_polygon_a << OpenStudio::Point3d.new(x + lengthXTarget * (v / totalFloorArea), y, z)

        # create core polygon
        core_polygon = OpenStudio::Point3dVector.new
        core_origin = OpenStudio::Point3d.new(x, y + perimeterDepth, z)
        core_polygon << core_origin
        core_polygon << OpenStudio::Point3d.new(x, y + lengthYTarget - perimeterDepth, z)
        core_polygon << OpenStudio::Point3d.new(x + lengthXTarget * (v / totalFloorArea), y + lengthYTarget - perimeterDepth, z)
        core_polygon << OpenStudio::Point3d.new(x + lengthXTarget * (v / totalFloorArea), y + perimeterDepth, z)

        # perimeter polygon b                              w
        perim_polygon_b = OpenStudio::Point3dVector.new
        perim_origin_b = OpenStudio::Point3d.new(x, y + lengthYTarget - perimeterDepth, z)
        perim_polygon_b << perim_origin_b
        perim_polygon_b << OpenStudio::Point3d.new(x, y + lengthYTarget, z)
        perim_polygon_b << OpenStudio::Point3d.new(x + lengthXTarget * (v / totalFloorArea), y + lengthYTarget, z)
        perim_polygon_b << OpenStudio::Point3d.new(x + lengthXTarget * (v / totalFloorArea), y + lengthYTarget - perimeterDepth, z)

        # run method to make spaces
        # todo - standards methods are not found here
        tempSpaceArray << OpenstudioStandards::Geometry.create_space_from_polygon(model, perim_origin_a, perim_polygon_a, options) # model, origin, polygon, options
        tempSpaceArray << OpenstudioStandards::Geometry.create_space_from_polygon(model, core_origin, core_polygon, options) # model, origin, polygon, options
        tempSpaceArray << OpenstudioStandards::Geometry.create_space_from_polygon(model, perim_origin_b, perim_polygon_b, options) # model, origin, polygon, options

      elsif lengthYTarget > perimeterDepth * 2 # slice into two peremeter zones but no core

        # perimeter polygon a
        perim_polygon_a = OpenStudio::Point3dVector.new
        perim_origin_a = OpenStudio::Point3d.new(x, y, z)
        perim_polygon_a << perim_origin_a
        perim_polygon_a << OpenStudio::Point3d.new(x, y + lengthYTarget / 2, z)
        perim_polygon_a << OpenStudio::Point3d.new(x + lengthXTarget * (v / totalFloorArea), y + lengthYTarget / 2, z)
        perim_polygon_a << OpenStudio::Point3d.new(x + lengthXTarget * (v / totalFloorArea), y, z)

        # perimeter polygon b
        perim_polygon_b = OpenStudio::Point3dVector.new
        perim_origin_b = OpenStudio::Point3d.new(x, y + lengthYTarget / 2, z)
        perim_polygon_b << perim_origin_b
        perim_polygon_b << OpenStudio::Point3d.new(x, y + lengthYTarget, z)
        perim_polygon_b << OpenStudio::Point3d.new(x + lengthXTarget * (v / totalFloorArea), y + lengthYTarget, z)
        perim_polygon_b << OpenStudio::Point3d.new(x + lengthXTarget * (v / totalFloorArea), y + lengthYTarget / 2, z)

        # run method to make spaces
        tempSpaceArray << OpenStudioStandards::Geometry.create_space_from_polygon(model, perim_origin_a, perim_polygon_a, options) # model, origin, polygon, options
        tempSpaceArray << OpenStudioStandards::Geometry.create_space_from_polygon(model, perim_origin_b, perim_polygon_b, options) # model, origin, polygon, options

      else # don't slice into core and perimeter

        # create polygon
        core_polygon = OpenStudio::Point3dVector.new
        core_origin = OpenStudio::Point3d.new(x, y, z)
        core_polygon << core_origin
        core_polygon << OpenStudio::Point3d.new(x, y + lengthYTarget, z)
        core_polygon << OpenStudio::Point3d.new(x + lengthXTarget * (v / totalFloorArea), y + lengthYTarget, z)
        core_polygon << OpenStudio::Point3d.new(x + lengthXTarget * (v / totalFloorArea), y, z)

        # run method to make space
        tempSpaceArray << OpenStudioStandards::Geometry.create_space_from_polygon(model, core_origin, core_polygon, options) # model, origin, polygon, options

      end

      # update points for next run
      x += lengthXTarget * (v / totalFloorArea)
    end

    # set flags for adiabatic surfaces
    floorAdiabatic = false
    ceilingAdiabatic = false

    # update z
    if midFloorMultiplier == 1
      z += floor_to_floor_height
    else
      z += floor_to_floor_height * midFloorMultiplier - floor_to_floor_height

      case storyCounter
      when 0
        ceilingAdiabatic = true
      when 1
        floorAdiabatic = true
        ceilingAdiabatic = true
      else
        floorAdiabatic = true
      end

      # alter surfaces boundary conditions and constructions as described above
      tempSpaceArray.each do |space|
        space.surfaces.each do |surface|
          if (surface.surfaceType == 'RoofCeiling') && ceilingAdiabatic
            construction = surface.construction # TODO: - this isn't really the construction I want since it wasn't an interior one, but will work for now
            surface.setOutsideBoundaryCondition('Adiabatic')
            if !construction.empty?
              surface.setConstruction(construction.get)
            end
          end
          if (surface.surfaceType == 'Floor') && floorAdiabatic
            construction = surface.construction # TODO: - this isn't really the construction I want since it wasn't an interior one, but will work for now
            surface.setOutsideBoundaryCondition('Adiabatic')
            if !construction.empty?
              surface.setConstruction(construction.get)
            end
          end
        end
      end

      # populate bar space array from temp array
      barSpaceArray << tempSpaceArray

    end

    # update storyCounter
    storyCounter += 1
  end

  # surface matching (seems more complex than necessary)
  spaces = OpenStudio::Model::SpaceVector.new
  model.getSpaces.each do |space|
    spaces << space
  end
  OpenStudio::Model.matchSurfaces(spaces)

  result = barSpaceArray
  return result
end