Class: BTAP::Activity
- Inherits:
-
Object
- Object
- BTAP::Activity
- Extended by:
- ActivityData
- Defined in:
- lib/openstudio-standards/btap/activity.rb
Instance Attribute Summary collapse
-
#activities ⇒ Hash
readonly
Collection of space ACTIVITIES (e.g. “bulk::warehouse”).
-
#activity ⇒ String
readonly
Assigned or inferred building ACTIVITY (e.g. “warehouse”).
-
#category ⇒ String
readonly
Building type CATEGORY (e.g. “industry”).
-
#feedback ⇒ Hash
readonly
Logged messages.
-
#liveload ⇒ Float
readonly
Expected non-occupant liveload (e.g. 90 kg/m2).
Instance Method Summary collapse
-
#getBuildingActivity(model = nil) ⇒ String
Determines general building activity, either set by user or inferred.
-
#getSpaceActivities(model = nil) ⇒ Hash
Gather activities of occupied spaces in a model.
-
#initialize(model = nil) ⇒ Activity
constructor
Initialize BTAP Activity parameters.
Methods included from ActivityData
Constructor Details
#initialize(model = nil) ⇒ Activity
Initialize BTAP Activity parameters.
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/openstudio-standards/btap/activity.rb', line 218 def initialize(model = nil) mth = "BTAP::Activity::#{__callee__}" @feedback = {logs: []} lgs = @feedback[:logs] @activity = "" @activities = {} @category = "" unless model.is_a?(OpenStudio::Model::Model) lgs << "Invalid or empty OpenStudio model (#{mth})" return end # Tag spaces as un/conditioned with "space_conditioning_category". For # now, this is simply determined based on whether spaces are: # - part of the total floor area (i.e. occupied) # - have "attic" included in their identifiers (i.e. unconditioned) # # As per ASHRE 90.1, OpenStudio-Standards distinguishes between: # - "nonresconditioned" vs # - "resconditioned" # # Sticking to "nonresconditioned" - NECBs do not distinguish between "res" # vs "non-res" (for e.g. envelope), as opposed to ASHRAE 90.1. # # The solution could be further refined in future BTAP versions by e.g.: # - relying on user-defined thermostats # - expanded to cover semi-heated and refrigerated spaces tag = "space_conditioning_category" model.getSpaces.each do |space| next unless space.additionalProperties.getFeatureAsString(tag).empty? if space.partofTotalFloorArea space.additionalProperties.setFeature(tag, "nonresconditioned") else if space.nameString.downcase.include?("attic") space.additionalProperties.setFeature(tag, "unconditioned") else # treat all other cases as indirectly-conditioned e.g. plenums space.additionalProperties.setFeature(tag, "nonresconditioned") end end end # Determine activities of occupied spaces in the model, then building. @activities = self.getSpaceActivities(model) @activity = self.getBuildingActivity(model) @liveload = data[:bldg][:activity][@activity][:liveload] # Assign building category. unless @activity.empty? @category = data[:bldg][:activity][@activity][:category] end true end |
Instance Attribute Details
#activities ⇒ Hash (readonly)
Returns collection of space ACTIVITIES (e.g. “bulk::warehouse”).
202 203 204 |
# File 'lib/openstudio-standards/btap/activity.rb', line 202 def activities @activities end |
#activity ⇒ String (readonly)
Returns assigned or inferred building ACTIVITY (e.g. “warehouse”).
199 200 201 |
# File 'lib/openstudio-standards/btap/activity.rb', line 199 def activity @activity end |
#category ⇒ String (readonly)
Returns building type CATEGORY (e.g. “industry”).
205 206 207 |
# File 'lib/openstudio-standards/btap/activity.rb', line 205 def category @category end |
#feedback ⇒ Hash (readonly)
Returns logged messages.
211 212 213 |
# File 'lib/openstudio-standards/btap/activity.rb', line 211 def feedback @feedback end |
#liveload ⇒ Float (readonly)
Returns expected non-occupant liveload (e.g. 90 kg/m2).
208 209 210 |
# File 'lib/openstudio-standards/btap/activity.rb', line 208 def liveload @liveload end |
Instance Method Details
#getBuildingActivity(model = nil) ⇒ String
Determines general building activity, either set by user or inferred.
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 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 |
# File 'lib/openstudio-standards/btap/activity.rb', line 360 def getBuildingActivity(model = nil) mth = "BTAP::Activity::#{__callee__}" cl = OpenStudio::Model::Model return mismatch("model", model, cl, mth, DBG, "") unless model.is_a?(cl) # OPTION A: Extract building activity from user-set 'additionalProperty'. tag = "btap_building_activity" bldg = model.getBuilding activity = bldg.additionalProperties.getFeatureAsString(tag) if activity.empty? activity = "" else activity = activity.get.downcase return activity if data[:bldg][:activities].include?(activity) end # OPTION B: Extract building activity from user-set 'building type'. bldgtype = model.getBuilding.standardsBuildingType unless bldgtype.empty? bldgtype = bldgtype.get.downcase candidates = [] fallbacks = [] # Fetch matching BTAP data, if keywords included. data[:bldg][:activity].each do |k, v| v[:includes].each do |kword| candidates << k if bldgtype.include?(kword) end end # Keep track of fallbacks, if applicable. candidates.each do |candidate| fallback = data[:bldg][:activity][candidate][:fallback] fallbacks << fallback unless fallback.empty? end # Reject if matching excluded keywords. data[:bldg][:activity].each do |k, v| v[:excludes].each do |kword| candidates.delete(k) if bldgtype.include?(kword) end end # Fallbacks? if candidates.empty? fallbacks.each do |fallback| return fallback if data[:bldg][:activity].key?(fallback) end else return candidates.first end end # OPTION C: Infer building activity from distribution of spacetypes. bldgtypes = {} @activities.values.each do |v| next unless v.key?(:m2) next unless v.key?(:bldgtype) bldgtypes[v[:bldgtype]] = 0 unless bldgtypes.include?(v[:bldgtype]) bldgtypes[v[:bldgtype]] += v[:m2] end activity = bldgtypes.sort.reverse.to_h.keys.first unless bldgtypes.empty? # Many NECB space types are listed as "common". Examples include spaces # that are educational in nature (e.g. "classroom", "teachinglabs") and # typical office spaces (e.g. "openplan", "office"). This is odd, as NECBs # list "school/university" and "office" as admissible building types. # Inferring an overall building type/activity (e.g. "school"), based on # the prevalence of space types (e.g. "classrooms") in a model, becomes # unnecessarily challenging. A fallback solution is needed when # predominant space types end up as "common" for a given model. # # One odd exception is 'audience' seating for an "auditorium", which is # found in all NECB editions. All listed 'audience' seating space types # are linked to a listed building type, e.g.: # - "religious building" # - "sports arena" # - "motion picture theatre" # # ... except for "auditorium". No NECB edition holds an "auditorium" # building type entry. For the moment, "auditorium" will be associated # with the ubiquitous high-school or college auditorium. if activity == "common" activities = {} @activities.values.each do |v| next unless v.key?(:m2) next unless v.key?(:activity) activities[v[:activity]] = 0 unless activities.key?(v[:activity]) activities[v[:activity]] += v[:m2] end activity = case activities.sort.reverse.to_h.keys.first when "audience" then "school" when "sales" then "retail" when "dining" then "restaurant" when "cuisine" then "restaurant" when "rooms" then "hotel" when "recreation" then "exercise" when "cell" then "penitentiary" when "classroom" then "school" when "teachinglab" then "school" when "storage" then "warehouse" when "laundry" then "retail" when "lounge" then "leisure" when "pharmacy" then "retail" else "office" end end activity = "office" if activity.empty? activity end |
#getSpaceActivities(model = nil) ⇒ Hash
Gather activities of occupied spaces in a model.
281 282 283 284 285 286 287 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 |
# File 'lib/openstudio-standards/btap/activity.rb', line 281 def getSpaceActivities(model = nil) mth = "BTAP::Activity::#{__callee__}" cl = OpenStudio::Model::Model return mismatch("model", model, cl, mth, DBG, {}) unless model.is_a?(cl) activities = {} model.getSpaces.each do |space| next unless space.partofTotalFloorArea # Defaulted values (if missing or invalid entries). spacetype = nil standards = "" activity = "" bldgtype = "" fallbacks = [] candidates = [] # Recover user-set space types? unless space.spaceType.empty? spacetype = space.spaceType.get stdstype = spacetype.standardsSpaceType standards = stdstype.get.downcase unless stdstype.empty? end # Fetch matching BTAP data, if keywords included. data[:space][:activity].each do |k, v| v[:includes].each do |kword| candidates << k if standards.include?(kword) end end # Keep track of fallbacks, if applicable. candidates.each do |candidate| fallback = data[:space][:activity][candidate][:fallback] fallbacks << fallback unless fallback.empty? end # Reject if matching excluded keywords. data[:space][:activity].each do |k, v| v[:excludes].each do |kword| candidates.delete(k) if standards.include?(kword) end end # Fallbacks? if candidates.empty? candidate = "" fallbacks.each do |fallback| break unless candidate.empty? candidate = fallback if data[:space][:activity].key?(fallback) end candidate = data[:space][:activity].keys.first if candidate.empty? else candidate = candidates.first end entry = {} entry[:m2 ] = space.floorArea entry[:spacetype] = spacetype entry[:standards] = standards entry[:activity ] = data[:space][:activity][candidate][:activity] entry[:bldgtype ] = data[:space][:activity][candidate][:bldgtype] activities[space] = entry end activities end |