tbd 3.3.0 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 840a07d7ac8aab45d2c2e377c9aecfc7bfb6e02a2aa00736bd3d07da271d619e
4
- data.tar.gz: 0f41e81875c54f81c00e8788b40569bde04e75233fd3a7d1f9b5e905aecf866c
3
+ metadata.gz: 55fa99f5424c92aa2e6d8d8ad36c38258ed6bf6470e83b7ddfe76484e2305e6e
4
+ data.tar.gz: 4287113e3b51879461fd48b5172e4e338f76d310695932ba66a64a4d269a6908
5
5
  SHA512:
6
- metadata.gz: bf7839e2518c1fdff231b7f9ad9ac8a8b8fd6a2e3ca79e7441ca58c5c8d6dcf22d64ee6414fecd9160ec0cc1203f1a07ec862e7337ed27b1812f0ef59617d94b
7
- data.tar.gz: f3fe90266432320e562a7119a4f11c9097cb958533c4b9e1c53089330b2fd79ca15884c798f9f49f3cb751ca8374f10801f77a0b070f8f039c242e4874338863
6
+ metadata.gz: 364663c82eb9ff346e62ce14fa53ac99d72d8e4e13aea8b36c6ad1efce5ea5a592e5bef91d640113c16f82def4a4372e6970b5befe50c320c0a4377125e91323
7
+ data.tar.gz: b031ed88478b6f91b6f20285bd0c375bde08fa74bc5036aff153beb9dad485bb5eeaeec2a1deba525b2da63f14b8f8d6937183971818b23bd2012ebc94fded9a
@@ -111,8 +111,8 @@ jobs:
111
111
  run: |
112
112
  echo $(pwd)
113
113
  echo $(ls)
114
- docker pull nrel/openstudio:dev-3.7.0-alpha
115
- docker run --name test --rm -d -t -v $(pwd):/work -w /work nrel/openstudio:dev-3.7.0-alpha
114
+ docker pull nrel/openstudio:3.7.0
115
+ docker run --name test --rm -d -t -v $(pwd):/work -w /work nrel/openstudio:3.7.0
116
116
  docker exec -t test pwd
117
117
  docker exec -t test ls
118
118
  docker exec -t test bundle update
data/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2020-2023 Denis Bourgeois & Dan Macumber
3
+ Copyright (c) 2020-2024 Denis Bourgeois & Dan Macumber
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/json/tbd_z5.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "schema": "https://github.com/rd2/tbd/blob/master/tbd.schema.json",
3
+ "description": "testing TBD JSON for 5Zone (plenum)",
4
+ "psis": [{
5
+ "id": "salk",
6
+ "ceiling": 0.1
7
+ }],
8
+ "spaces": [{
9
+ "id": "PLENUM-1",
10
+ "psi": "salk"
11
+ }]
12
+ }
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2020-2023 Denis Bourgeois & Dan Macumber
3
+ Copyright (c) 2020-2024 Denis Bourgeois & Dan Macumber
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
  #
3
- # Copyright (c) 2020-2023 Denis Bourgeois & Dan Macumber
3
+ # Copyright (c) 2020-2024 Denis Bourgeois & Dan Macumber
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -3,8 +3,8 @@
3
3
  <schema_version>3.1</schema_version>
4
4
  <name>tbd_measure</name>
5
5
  <uid>8890787b-8c25-4dc8-8641-b6be1b6c2357</uid>
6
- <version_id>80f7038a-762a-4f4d-81f4-f4e9daa64925</version_id>
7
- <version_modified>2023-10-22T13:14:49Z</version_modified>
6
+ <version_id>bd35a453-60b3-4329-9699-3c7e8e49b5bf</version_id>
7
+ <version_modified>2024-01-01T12:58:55Z</version_modified>
8
8
  <xml_checksum>99772807</xml_checksum>
9
9
  <class_name>TBDMeasure</class_name>
10
10
  <display_name>Thermal Bridging and Derating - TBD</display_name>
@@ -464,7 +464,7 @@
464
464
  <filename>LICENSE.md</filename>
465
465
  <filetype>md</filetype>
466
466
  <usage_type>license</usage_type>
467
- <checksum>A91E64A0</checksum>
467
+ <checksum>5C9BFB50</checksum>
468
468
  </file>
469
469
  <file>
470
470
  <filename>README.md</filename>
@@ -493,13 +493,13 @@
493
493
  <filename>measure.rb</filename>
494
494
  <filetype>rb</filetype>
495
495
  <usage_type>script</usage_type>
496
- <checksum>D1FC18B2</checksum>
496
+ <checksum>A472E915</checksum>
497
497
  </file>
498
498
  <file>
499
499
  <filename>geo.rb</filename>
500
500
  <filetype>rb</filetype>
501
501
  <usage_type>resource</usage_type>
502
- <checksum>7A491A3B</checksum>
502
+ <checksum>1D9996A0</checksum>
503
503
  </file>
504
504
  <file>
505
505
  <filename>geometry.rb</filename>
@@ -523,13 +523,13 @@
523
523
  <filename>psi.rb</filename>
524
524
  <filetype>rb</filetype>
525
525
  <usage_type>resource</usage_type>
526
- <checksum>0CBB060B</checksum>
526
+ <checksum>9B29CA06</checksum>
527
527
  </file>
528
528
  <file>
529
529
  <filename>tbd.rb</filename>
530
530
  <filetype>rb</filetype>
531
531
  <usage_type>resource</usage_type>
532
- <checksum>A4E8433C</checksum>
532
+ <checksum>E8D38E59</checksum>
533
533
  </file>
534
534
  <file>
535
535
  <filename>transformation.rb</filename>
@@ -541,7 +541,7 @@
541
541
  <filename>ua.rb</filename>
542
542
  <filetype>rb</filetype>
543
543
  <usage_type>resource</usage_type>
544
- <checksum>1AEE3C54</checksum>
544
+ <checksum>928C5E7B</checksum>
545
545
  </file>
546
546
  <file>
547
547
  <filename>utils.rb</filename>
@@ -565,7 +565,7 @@
565
565
  <filename>tbd_tests.rb</filename>
566
566
  <filetype>rb</filetype>
567
567
  <usage_type>test</usage_type>
568
- <checksum>85067AF6</checksum>
568
+ <checksum>2ECE06CA</checksum>
569
569
  </file>
570
570
  </files>
571
571
  </measure>
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
  #
3
- # Copyright (c) 2020-2023 Denis Bourgeois & Dan Macumber
3
+ # Copyright (c) 2020-2024 Denis Bourgeois & Dan Macumber
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -347,6 +347,7 @@ module TBD
347
347
 
348
348
  surf[:conditioned] = surf.key?(:heating) || surf.key?(:cooling)
349
349
  surf[:space ] = space
350
+ surf[:occupied ] = space.partofTotalFloorArea
350
351
  surf[:boundary ] = facing
351
352
  surf[:ground ] = surface.isGroundSurface
352
353
  surf[:type ] = :floor
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
  #
3
- # Copyright (c) 2020-2023 Denis Bourgeois & Dan Macumber
3
+ # Copyright (c) 2020-2024 Denis Bourgeois & Dan Macumber
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -156,6 +156,7 @@ module TBD
156
156
  rimjoist: 1.000000, # re: BETBG
157
157
  parapet: 0.800000, # re: BETBG
158
158
  roof: 0.800000, # same as parapet
159
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
159
160
  fenestration: 0.500000, # re: BETBG
160
161
  door: 0.500000, # inferred, same as (vertical) fenestration
161
162
  skylight: 0.500000, # inferred, same as (vertical) fenestration
@@ -176,6 +177,7 @@ module TBD
176
177
  rimjoist: 0.500000, # re: BETBG
177
178
  parapet: 0.450000, # re: BETBG
178
179
  roof: 0.450000, # same as parapet
180
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
179
181
  fenestration: 0.350000, # re: BETBG
180
182
  door: 0.350000, # inferred, same as (vertical) fenestration
181
183
  skylight: 0.350000, # inferred, same as (vertical) fenestration
@@ -196,6 +198,7 @@ module TBD
196
198
  rimjoist: 0.200000, # re: BETBG
197
199
  parapet: 0.200000, # re: BETBG
198
200
  roof: 0.200000, # same as parapet
201
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
199
202
  fenestration: 0.199999, # re: BETBG
200
203
  door: 0.199999, # inferred, same as (vertical) fenestration
201
204
  skylight: 0.199999, # inferred, same as (vertical) fenestration
@@ -216,6 +219,7 @@ module TBD
216
219
  rimjoist: 0.615000, # Detail 1.2.1
217
220
  parapet: 1.000000, # Detail 1.3.2
218
221
  roof: 1.000000, # same as parapet
222
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
219
223
  fenestration: 0.000000, # inferred, generally part of clear-field RSi
220
224
  door: 0.000000, # inferred, generally part of clear-field RSi
221
225
  skylight: 0.350000, # same as "regular (BETBG)"
@@ -236,6 +240,7 @@ module TBD
236
240
  rimjoist: 0.170000, # Detail 1.2.7
237
241
  parapet: 0.660000, # Detail 1.3.2
238
242
  roof: 0.660000, # same as parapet
243
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
239
244
  fenestration: 0.000000, # inferred, generally part of clear-field RSi
240
245
  door: 0.000000, # inferred, generally part of clear-field RSi
241
246
  skylight: 0.350000, # same as "regular (BETBG)"
@@ -256,6 +261,7 @@ module TBD
256
261
  rimjoist: 0.300000, # re I1
257
262
  parapet: 0.325000, # re I1
258
263
  roof: 0.325000, # same as parapet
264
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
259
265
  fenestration: 0.200000, # re I1
260
266
  door: 0.200000, # re I1
261
267
  skylight: 0.200000, # re I1
@@ -276,6 +282,7 @@ module TBD
276
282
  rimjoist: 0.850000, # re I1
277
283
  parapet: 0.800000, # re I1
278
284
  roof: 0.800000, # same as parapet
285
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
279
286
  fenestration: 0.500000, # re I1
280
287
  door: 0.500000, # re I1
281
288
  skylight: 0.500000, # re I1
@@ -296,6 +303,7 @@ module TBD
296
303
  rimjoist: 0.307000, # "intermediate floor to wall intersection"
297
304
  parapet: 0.260000, # "parapet" edge
298
305
  roof: 0.020000, # (non-parapet) "roof" edge
306
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
299
307
  fenestration: 0.194000, # "wall to vertical fenestration intersection"
300
308
  door: 0.000000, # (unspecified, defaults to 0)
301
309
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -316,6 +324,7 @@ module TBD
316
324
  rimjoist: 0.842000, # "intermediate floor to wall intersection"
317
325
  parapet: 0.500000, # "parapet" edge
318
326
  roof: 0.650000, # (non-parapet) "roof" edge
327
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
319
328
  fenestration: 0.505000, # "wall to vertical fenestration intersection"
320
329
  door: 0.000000, # (unspecified, defaults to 0)
321
330
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -336,6 +345,7 @@ module TBD
336
345
  rimjoist: 0.205000, # "intermediate floor to wall intersection"
337
346
  parapet: 0.217000, # "parapet" edge
338
347
  roof: 0.150000, # (non-parapet) "roof" edge
348
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
339
349
  fenestration: 0.226000, # "wall to vertical fenestration intersection"
340
350
  door: 0.000000, # (unspecified, defaults to 0)
341
351
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -356,6 +366,7 @@ module TBD
356
366
  rimjoist: 0.824000, # "intermediate floor to wall intersection"
357
367
  parapet: 0.412000, # "parapet" edge
358
368
  roof: 0.750000, # (non-parapet) "roof" edge
369
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
359
370
  fenestration: 0.325000, # "wall to vertical fenestration intersection"
360
371
  door: 0.000000, # (unspecified, defaults to 0)
361
372
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -376,6 +387,7 @@ module TBD
376
387
  rimjoist: 0.495000, # "intermediate floor to wall intersection"
377
388
  parapet: 0.393000, # "parapet" edge
378
389
  roof: 0.150000, # (non-parapet) "roof" edge
390
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
379
391
  fenestration: 0.143000, # "wall to vertical fenestration intersection"
380
392
  door: 0.000000, # (unspecified, defaults to 0)
381
393
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -396,6 +408,7 @@ module TBD
396
408
  rimjoist: 0.824000, # "intermediate floor to wall intersection"
397
409
  parapet: 0.884000, # "parapet" edge
398
410
  roof: 0.750000, # (non-parapet) "roof" edge
411
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
399
412
  fenestration: 0.543000, # "wall to vertical fenestration intersection"
400
413
  door: 0.000000, # (unspecified, defaults to 0)
401
414
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -416,6 +429,7 @@ module TBD
416
429
  rimjoist: 0.084000, # "intermediate floor to wall intersection"
417
430
  parapet: 0.056000, # "parapet" edge
418
431
  roof: 0.020000, # (non-parapet) "roof" edge
432
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
419
433
  fenestration: 0.171000, # "wall to vertical fenestration intersection"
420
434
  door: 0.000000, # (unspecified, defaults to 0)
421
435
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -436,6 +450,7 @@ module TBD
436
450
  rimjoist: 0.582000, # "intermediate floor to wall intersection"
437
451
  parapet: 0.056000, # "parapet" edge
438
452
  roof: 0.150000, # (non-parapet) "roof" edge
453
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
439
454
  fenestration: 0.260000, # "wall to vertical fenestration intersection"
440
455
  door: 0.000000, # (unspecified, defaults to 0)
441
456
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -452,20 +467,22 @@ module TBD
452
467
 
453
468
  @set["(non thermal bridging)"] =
454
469
  {
455
- rimjoist: 0.000000, # defaults to 0
456
- parapet: 0.000000, # defaults to 0
457
- roof: 0.000000, # defaults to 0
458
- fenestration: 0.000000, # defaults to 0
459
- door: 0.000000, # defaults to 0
460
- skylight: 0.000000, # defaults to 0
461
- spandrel: 0.000000, # defaults to 0
462
- corner: 0.000000, # defaults to 0
463
- balcony: 0.000000, # defaults to 0
464
- balconysill: 0.000000, # defaults to 0
465
- party: 0.000000, # defaults to 0
466
- grade: 0.000000, # defaults to 0
467
- joint: 0.000000, # defaults to 0
468
- transition: 0.000000 # defaults to 0
470
+ rimjoist: 0.000000, # defaults to 0
471
+ parapet: 0.000000, # defaults to 0
472
+ roof: 0.000000, # defaults to 0
473
+ ceiling: 0.000000, # defaults to 0
474
+ fenestration: 0.000000, # defaults to 0
475
+ door: 0.000000, # defaults to 0
476
+ skylight: 0.000000, # defaults to 0
477
+ spandrel: 0.000000, # defaults to 0
478
+ corner: 0.000000, # defaults to 0
479
+ balcony: 0.000000, # defaults to 0
480
+ balconysill: 0.000000, # defaults to 0
481
+ balconydoorsill: 0.000000, # defaults to 0
482
+ party: 0.000000, # defaults to 0
483
+ grade: 0.000000, # defaults to 0
484
+ joint: 0.000000, # defaults to 0
485
+ transition: 0.000000 # defaults to 0
469
486
  }.freeze
470
487
 
471
488
  @set.keys.each { |k| self.gen(k) }
@@ -530,6 +547,9 @@ module TBD
530
547
  h[:roof ] = @set[id].key?(:roof)
531
548
  h[:roofconcave ] = @set[id].key?(:roofconcave)
532
549
  h[:roofconvex ] = @set[id].key?(:roofconvex)
550
+ h[:ceiling ] = @set[id].key?(:ceiling)
551
+ h[:ceilingconcave ] = @set[id].key?(:ceilingconcave)
552
+ h[:ceilingconvex ] = @set[id].key?(:ceilingconvex)
533
553
  h[:grade ] = @set[id].key?(:grade)
534
554
  h[:gradeconcave ] = @set[id].key?(:gradeconcave)
535
555
  h[:gradeconvex ] = @set[id].key?(:gradeconvex)
@@ -562,6 +582,7 @@ module TBD
562
582
  v[:corner ] = 0; v[:cornerconcave ] = 0; v[:cornerconvex ] = 0
563
583
  v[:parapet ] = 0; v[:parapetconcave ] = 0; v[:parapetconvex ] = 0
564
584
  v[:roof ] = 0; v[:roofconcave ] = 0; v[:roofconvex ] = 0
585
+ v[:ceiling ] = 0; v[:ceilingconcave ] = 0; v[:ceilingconvex ] = 0
565
586
  v[:party ] = 0; v[:partyconcave ] = 0; v[:partyconvex ] = 0
566
587
  v[:grade ] = 0; v[:gradeconcave ] = 0; v[:gradeconvex ] = 0
567
588
  v[:balcony ] = 0; v[:balconyconcave ] = 0; v[:balconyconvex ] = 0
@@ -697,6 +718,11 @@ module TBD
697
718
  v[:roofconvex ] = @set[id][:roof ] if h[:roof ]
698
719
  v[:roofconcave ] = @set[id][:roofconcave ] if h[:roofconcave ]
699
720
  v[:roofconvex ] = @set[id][:roofconvex ] if h[:roofconvex ]
721
+ v[:ceiling ] = @set[id][:ceiling ] if h[:ceiling ]
722
+ v[:ceilingconcave ] = @set[id][:ceiling ] if h[:ceiling ]
723
+ v[:ceilingconvex ] = @set[id][:ceiling ] if h[:ceiling ]
724
+ v[:ceilingconcave ] = @set[id][:ceilingconcave ] if h[:ceilingconcave ]
725
+ v[:ceilingconvex ] = @set[id][:ceilingconvex ] if h[:ceilingconvex ]
700
726
  v[:party ] = @set[id][:party ] if h[:party ]
701
727
  v[:partyconcave ] = @set[id][:party ] if h[:party ]
702
728
  v[:partyconvex ] = @set[id][:party ] if h[:party ]
@@ -764,6 +790,7 @@ module TBD
764
790
 
765
791
  max = [v[:roofconcave], v[:roofconvex]].max
766
792
  v[:roof] = max unless @has[:roof]
793
+
767
794
  @val[id] = v
768
795
 
769
796
  true
@@ -783,6 +810,9 @@ module TBD
783
810
  # @option set [#to_f] :roof roof-to-wall intersection
784
811
  # @option set [#to_f] :roofconcave basilaire variant
785
812
  # @option set [#to_f] :roofconvex typical
813
+ # @option set [#to_f] :ceiling intermediate (uninsulated) ceiling perimeter
814
+ # @option set [#to_f] :ceilingconcave cantilever variant
815
+ # @option set [#to_f] :ceilingconvex colonnade variant
786
816
  # @option set [#to_f] :fenestration head/sill/jamb interface
787
817
  # @option set [#to_f] :head (fenestrated) header interface
788
818
  # @option set [#to_f] :headconcave (fenestrated) basilaire variant
@@ -870,6 +900,9 @@ module TBD
870
900
  s[:roof ] = set[:roof ] if set.key?(:roof)
871
901
  s[:roofconcave ] = set[:roofconcave ] if set.key?(:roofconcave)
872
902
  s[:roofconvex ] = set[:roofconvex ] if set.key?(:roofconvex)
903
+ s[:ceiling ] = set[:ceiling ] if set.key?(:ceiling)
904
+ s[:ceilingconcave ] = set[:ceilingconcave ] if set.key?(:ceilingconcave)
905
+ s[:ceilingconvex ] = set[:ceilingconvex ] if set.key?(:ceilingconvex)
873
906
  s[:fenestration ] = set[:fenestration ] if set.key?(:fenestration)
874
907
  s[:head ] = set[:head ] if set.key?(:head)
875
908
  s[:headconcave ] = set[:headconcave ] if set.key?(:headconcave)
@@ -926,6 +959,7 @@ module TBD
926
959
 
927
960
  s[:joint ] = 0.000 unless set.key?(:joint)
928
961
  s[:transition ] = 0.000 unless set.key?(:transition)
962
+ s[:ceiling ] = 0.000 unless set.key?(:ceiling)
929
963
 
930
964
  @set[id] = s
931
965
  self.gen(id)
@@ -941,13 +975,13 @@ module TBD
941
975
  #
942
976
  # @param id [#to_s] PSI set identifier
943
977
  # @example intermediate floor slab intersection
944
- # shorthands("A901")
978
+ # shorthands("90.1.22|steel.m|default")
945
979
  #
946
980
  # @return [Hash] has: Hash (Bool), val: Hash (PSI factors) see logs if empty
947
981
  def shorthands(id = "")
948
982
  mth = "TBD::#{__callee__}"
949
983
  sh = { has: {}, val: {} }
950
- id = trim(id)
984
+ id = trim(id)
951
985
  return mismatch("set ID", id, String, mth, ERR, a) if id.empty?
952
986
  return hashkey(id, @set , id, mth, ERR, sh) unless @set.key?(id)
953
987
  return hashkey(id, @has , id, mth, ERR, sh) unless @has.key?(id)
@@ -969,7 +1003,7 @@ module TBD
969
1003
  def complete?(id = "")
970
1004
  mth = "TBD::#{__callee__}"
971
1005
  a = false
972
- id = trim(id)
1006
+ id = trim(id)
973
1007
  return mismatch("set ID", id, String, mth, ERR, a) if id.empty?
974
1008
  return hashkey(id, @set , id, mth, ERR, a) unless @set.key?(id)
975
1009
  return hashkey(id, @has , id, mth, ERR, a) unless @has.key?(id)
@@ -1853,9 +1887,6 @@ module TBD
1853
1887
 
1854
1888
  # Evaluate current set content before processing a new linked surface.
1855
1889
  is = {}
1856
- is[:head ] = set.keys.to_s.include?("head")
1857
- is[:sill ] = set.keys.to_s.include?("sill")
1858
- is[:jamb ] = set.keys.to_s.include?("jamb")
1859
1890
  is[:doorhead ] = set.keys.to_s.include?("doorhead")
1860
1891
  is[:doorsill ] = set.keys.to_s.include?("doorsill")
1861
1892
  is[:doorjamb ] = set.keys.to_s.include?("doorjamb")
@@ -1866,6 +1897,7 @@ module TBD
1866
1897
  is[:corner ] = set.keys.to_s.include?("corner")
1867
1898
  is[:parapet ] = set.keys.to_s.include?("parapet")
1868
1899
  is[:roof ] = set.keys.to_s.include?("roof")
1900
+ is[:ceiling ] = set.keys.to_s.include?("ceiling")
1869
1901
  is[:party ] = set.keys.to_s.include?("party")
1870
1902
  is[:grade ] = set.keys.to_s.include?("grade")
1871
1903
  is[:balcony ] = set.keys.to_s.include?("balcony")
@@ -1873,6 +1905,12 @@ module TBD
1873
1905
  is[:balconydoorsill ] = set.keys.to_s.include?("balconydoorsill")
1874
1906
  is[:rimjoist ] = set.keys.to_s.include?("rimjoist")
1875
1907
 
1908
+ if is.empty?
1909
+ is[:head] = set.keys.to_s.include?("head")
1910
+ is[:sill] = set.keys.to_s.include?("sill")
1911
+ is[:jamb] = set.keys.to_s.include?("jamb")
1912
+ end
1913
+
1876
1914
  # Label edge as ...
1877
1915
  # :head, :sill, :jamb (vertical fenestration)
1878
1916
  # :doorhead, :doorsill, :doorjamb (opaque door)
@@ -2092,6 +2130,41 @@ module TBD
2092
2130
  is[:corner ] = true
2093
2131
  end
2094
2132
 
2133
+ # Label edge as :ceiling if linked to:
2134
+ # +1 deratable surfaces
2135
+ # 1x underatable CONDITIONED floor linked to an unoccupied space
2136
+ # 1x adjacent CONDITIONED ceiling linked to an occupied space
2137
+ edge[:surfaces].keys.each do |i|
2138
+ break if is[:ceiling]
2139
+ break unless deratables.size > 0
2140
+ break if floors.key?(id)
2141
+ next if i == id
2142
+ next unless floors.key?(i)
2143
+ next if floors[i][:ground ]
2144
+ next unless floors[i][:conditioned]
2145
+ next if floors[i][:occupied ]
2146
+
2147
+ ceiling = floors[i][:boundary]
2148
+ next unless ceilings.key?(ceiling)
2149
+ next unless ceilings[ceiling][:conditioned]
2150
+ next unless ceilings[ceiling][:occupied ]
2151
+
2152
+ other = deratables.first unless deratables.first == id
2153
+ other = deratables.last unless deratables.last == id
2154
+ other = id if deratables.size == 1
2155
+
2156
+ s1 = edge[:surfaces][id]
2157
+ s2 = edge[:surfaces][other]
2158
+ concave = concave?(s1, s2)
2159
+ convex = convex?(s1, s2)
2160
+ flat = !concave && !convex
2161
+
2162
+ set[:ceiling ] = shorts[:val][:ceiling ] if flat
2163
+ set[:ceilingconcave] = shorts[:val][:ceilingconcave] if concave
2164
+ set[:ceilingconvex ] = shorts[:val][:ceilingconvex ] if convex
2165
+ is[:ceiling ] = true
2166
+ end
2167
+
2095
2168
  # Label edge as :parapet/:roof if linked to:
2096
2169
  # 1x deratable wall
2097
2170
  # 1x deratable ceiling
@@ -2172,22 +2245,23 @@ module TBD
2172
2245
  is[:grade ] = true
2173
2246
  end
2174
2247
 
2175
- # Label edge as :rimjoist, :balcony, :balconysill or :balconydoorsill if linked to:
2248
+ # Label edge as :rimjoist, :balcony, :balconysill or :balconydoorsill,
2249
+ # if linked to:
2176
2250
  # 1x deratable surface
2177
2251
  # 1x CONDITIONED floor
2178
2252
  # 1x shade (optional)
2179
2253
  # 1x subsurface (optional)
2180
- #
2181
- # Despite referring to 'sill' or 'doorsill', a 'balconysill' or
2182
- # 'balconydoorsill' edge may instead link (rarer) cases of balcony and a
2183
- # fenestratio/door head. ASHRAE 90.1 2022 does not make the distinction
2184
- # between sill vs head when intermediatre floor, balcony and vertical
2185
- # fenestration meet. 'Sills' are simply the most common occurrence.
2186
2254
  balcony = false
2187
2255
  balconysill = false # vertical fenestration
2188
2256
  balconydoorsill = false # opaque door
2189
2257
 
2258
+ # Despite referring to 'sill' or 'doorsill', a 'balconysill' or
2259
+ # 'balconydoorsill' edge may instead link (rarer) cases of balcony and a
2260
+ # fenestration/door head. ASHRAE 90.1 2022 does not make the distinction
2261
+ # between sill vs head when intermediate floor, balcony and vertical
2262
+ # fenestration meet. 'Sills' are simply the most common occurrence.
2190
2263
  edge[:surfaces].keys.each do |i|
2264
+ break if is[:ceiling]
2191
2265
  break if balcony
2192
2266
  next if i == id
2193
2267
 
@@ -2259,15 +2333,17 @@ module TBD
2259
2333
  end
2260
2334
 
2261
2335
  edge[:surfaces].keys.each do |i|
2262
- break if is[:rimjoist ] || is[:balcony ] ||
2263
- is[:balconysill] || is[:balconydoorsill]
2336
+ break if is[:ceiling ]
2337
+ break if is[:rimjoist ]
2338
+ break if is[:balcony ]
2339
+ break if is[:balconysill ]
2340
+ break if is[:balconydoorsill]
2264
2341
  break unless deratables.size > 0
2265
2342
  break if floors.key?(id)
2266
2343
  next if i == id
2267
2344
  next unless floors.key?(i)
2268
- next unless floors[i].key?(:conditioned)
2269
- next unless floors[i][:conditioned]
2270
2345
  next if floors[i][:ground ]
2346
+ next unless floors[i][:conditioned]
2271
2347
 
2272
2348
  other = deratables.first unless deratables.first == id
2273
2349
  other = deratables.last unless deratables.last == id
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
  #
3
- # Copyright (c) 2020-2023 Denis Bourgeois & Dan Macumber
3
+ # Copyright (c) 2020-2024 Denis Bourgeois & Dan Macumber
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
  #
3
- # Copyright (c) 2020-2023 Denis Bourgeois & Dan Macumber
3
+ # Copyright (c) 2020-2024 Denis Bourgeois & Dan Macumber
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -1000,7 +1000,7 @@ module TBD
1000
1000
  model = "* modèle : #{ua[:file]}" if ua.key?(:file) && lang == :fr
1001
1001
  model += " (v#{ua[:version]})" if ua.key?(:version)
1002
1002
  report << model unless model.empty?
1003
- report << "* TBD : v3.3.0"
1003
+ report << "* TBD : v3.4.0"
1004
1004
  report << "* date : #{ua[:date]}"
1005
1005
 
1006
1006
  if lang == :en
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
  #
3
- # Copyright (c) 2020-2023 Denis Bourgeois & Dan Macumber
3
+ # Copyright (c) 2020-2024 Denis Bourgeois & Dan Macumber
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
data/lib/tbd/geo.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
  #
3
- # Copyright (c) 2020-2023 Denis Bourgeois & Dan Macumber
3
+ # Copyright (c) 2020-2024 Denis Bourgeois & Dan Macumber
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -347,6 +347,7 @@ module TBD
347
347
 
348
348
  surf[:conditioned] = surf.key?(:heating) || surf.key?(:cooling)
349
349
  surf[:space ] = space
350
+ surf[:occupied ] = space.partofTotalFloorArea
350
351
  surf[:boundary ] = facing
351
352
  surf[:ground ] = surface.isGroundSurface
352
353
  surf[:type ] = :floor
data/lib/tbd/psi.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
  #
3
- # Copyright (c) 2020-2023 Denis Bourgeois & Dan Macumber
3
+ # Copyright (c) 2020-2024 Denis Bourgeois & Dan Macumber
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -156,6 +156,7 @@ module TBD
156
156
  rimjoist: 1.000000, # re: BETBG
157
157
  parapet: 0.800000, # re: BETBG
158
158
  roof: 0.800000, # same as parapet
159
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
159
160
  fenestration: 0.500000, # re: BETBG
160
161
  door: 0.500000, # inferred, same as (vertical) fenestration
161
162
  skylight: 0.500000, # inferred, same as (vertical) fenestration
@@ -176,6 +177,7 @@ module TBD
176
177
  rimjoist: 0.500000, # re: BETBG
177
178
  parapet: 0.450000, # re: BETBG
178
179
  roof: 0.450000, # same as parapet
180
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
179
181
  fenestration: 0.350000, # re: BETBG
180
182
  door: 0.350000, # inferred, same as (vertical) fenestration
181
183
  skylight: 0.350000, # inferred, same as (vertical) fenestration
@@ -196,6 +198,7 @@ module TBD
196
198
  rimjoist: 0.200000, # re: BETBG
197
199
  parapet: 0.200000, # re: BETBG
198
200
  roof: 0.200000, # same as parapet
201
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
199
202
  fenestration: 0.199999, # re: BETBG
200
203
  door: 0.199999, # inferred, same as (vertical) fenestration
201
204
  skylight: 0.199999, # inferred, same as (vertical) fenestration
@@ -216,6 +219,7 @@ module TBD
216
219
  rimjoist: 0.615000, # Detail 1.2.1
217
220
  parapet: 1.000000, # Detail 1.3.2
218
221
  roof: 1.000000, # same as parapet
222
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
219
223
  fenestration: 0.000000, # inferred, generally part of clear-field RSi
220
224
  door: 0.000000, # inferred, generally part of clear-field RSi
221
225
  skylight: 0.350000, # same as "regular (BETBG)"
@@ -236,6 +240,7 @@ module TBD
236
240
  rimjoist: 0.170000, # Detail 1.2.7
237
241
  parapet: 0.660000, # Detail 1.3.2
238
242
  roof: 0.660000, # same as parapet
243
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
239
244
  fenestration: 0.000000, # inferred, generally part of clear-field RSi
240
245
  door: 0.000000, # inferred, generally part of clear-field RSi
241
246
  skylight: 0.350000, # same as "regular (BETBG)"
@@ -256,6 +261,7 @@ module TBD
256
261
  rimjoist: 0.300000, # re I1
257
262
  parapet: 0.325000, # re I1
258
263
  roof: 0.325000, # same as parapet
264
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
259
265
  fenestration: 0.200000, # re I1
260
266
  door: 0.200000, # re I1
261
267
  skylight: 0.200000, # re I1
@@ -276,6 +282,7 @@ module TBD
276
282
  rimjoist: 0.850000, # re I1
277
283
  parapet: 0.800000, # re I1
278
284
  roof: 0.800000, # same as parapet
285
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
279
286
  fenestration: 0.500000, # re I1
280
287
  door: 0.500000, # re I1
281
288
  skylight: 0.500000, # re I1
@@ -296,6 +303,7 @@ module TBD
296
303
  rimjoist: 0.307000, # "intermediate floor to wall intersection"
297
304
  parapet: 0.260000, # "parapet" edge
298
305
  roof: 0.020000, # (non-parapet) "roof" edge
306
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
299
307
  fenestration: 0.194000, # "wall to vertical fenestration intersection"
300
308
  door: 0.000000, # (unspecified, defaults to 0)
301
309
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -316,6 +324,7 @@ module TBD
316
324
  rimjoist: 0.842000, # "intermediate floor to wall intersection"
317
325
  parapet: 0.500000, # "parapet" edge
318
326
  roof: 0.650000, # (non-parapet) "roof" edge
327
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
319
328
  fenestration: 0.505000, # "wall to vertical fenestration intersection"
320
329
  door: 0.000000, # (unspecified, defaults to 0)
321
330
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -336,6 +345,7 @@ module TBD
336
345
  rimjoist: 0.205000, # "intermediate floor to wall intersection"
337
346
  parapet: 0.217000, # "parapet" edge
338
347
  roof: 0.150000, # (non-parapet) "roof" edge
348
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
339
349
  fenestration: 0.226000, # "wall to vertical fenestration intersection"
340
350
  door: 0.000000, # (unspecified, defaults to 0)
341
351
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -356,6 +366,7 @@ module TBD
356
366
  rimjoist: 0.824000, # "intermediate floor to wall intersection"
357
367
  parapet: 0.412000, # "parapet" edge
358
368
  roof: 0.750000, # (non-parapet) "roof" edge
369
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
359
370
  fenestration: 0.325000, # "wall to vertical fenestration intersection"
360
371
  door: 0.000000, # (unspecified, defaults to 0)
361
372
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -376,6 +387,7 @@ module TBD
376
387
  rimjoist: 0.495000, # "intermediate floor to wall intersection"
377
388
  parapet: 0.393000, # "parapet" edge
378
389
  roof: 0.150000, # (non-parapet) "roof" edge
390
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
379
391
  fenestration: 0.143000, # "wall to vertical fenestration intersection"
380
392
  door: 0.000000, # (unspecified, defaults to 0)
381
393
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -396,6 +408,7 @@ module TBD
396
408
  rimjoist: 0.824000, # "intermediate floor to wall intersection"
397
409
  parapet: 0.884000, # "parapet" edge
398
410
  roof: 0.750000, # (non-parapet) "roof" edge
411
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
399
412
  fenestration: 0.543000, # "wall to vertical fenestration intersection"
400
413
  door: 0.000000, # (unspecified, defaults to 0)
401
414
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -416,6 +429,7 @@ module TBD
416
429
  rimjoist: 0.084000, # "intermediate floor to wall intersection"
417
430
  parapet: 0.056000, # "parapet" edge
418
431
  roof: 0.020000, # (non-parapet) "roof" edge
432
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
419
433
  fenestration: 0.171000, # "wall to vertical fenestration intersection"
420
434
  door: 0.000000, # (unspecified, defaults to 0)
421
435
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -436,6 +450,7 @@ module TBD
436
450
  rimjoist: 0.582000, # "intermediate floor to wall intersection"
437
451
  parapet: 0.056000, # "parapet" edge
438
452
  roof: 0.150000, # (non-parapet) "roof" edge
453
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
439
454
  fenestration: 0.260000, # "wall to vertical fenestration intersection"
440
455
  door: 0.000000, # (unspecified, defaults to 0)
441
456
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -452,20 +467,22 @@ module TBD
452
467
 
453
468
  @set["(non thermal bridging)"] =
454
469
  {
455
- rimjoist: 0.000000, # defaults to 0
456
- parapet: 0.000000, # defaults to 0
457
- roof: 0.000000, # defaults to 0
458
- fenestration: 0.000000, # defaults to 0
459
- door: 0.000000, # defaults to 0
460
- skylight: 0.000000, # defaults to 0
461
- spandrel: 0.000000, # defaults to 0
462
- corner: 0.000000, # defaults to 0
463
- balcony: 0.000000, # defaults to 0
464
- balconysill: 0.000000, # defaults to 0
465
- party: 0.000000, # defaults to 0
466
- grade: 0.000000, # defaults to 0
467
- joint: 0.000000, # defaults to 0
468
- transition: 0.000000 # defaults to 0
470
+ rimjoist: 0.000000, # defaults to 0
471
+ parapet: 0.000000, # defaults to 0
472
+ roof: 0.000000, # defaults to 0
473
+ ceiling: 0.000000, # defaults to 0
474
+ fenestration: 0.000000, # defaults to 0
475
+ door: 0.000000, # defaults to 0
476
+ skylight: 0.000000, # defaults to 0
477
+ spandrel: 0.000000, # defaults to 0
478
+ corner: 0.000000, # defaults to 0
479
+ balcony: 0.000000, # defaults to 0
480
+ balconysill: 0.000000, # defaults to 0
481
+ balconydoorsill: 0.000000, # defaults to 0
482
+ party: 0.000000, # defaults to 0
483
+ grade: 0.000000, # defaults to 0
484
+ joint: 0.000000, # defaults to 0
485
+ transition: 0.000000 # defaults to 0
469
486
  }.freeze
470
487
 
471
488
  @set.keys.each { |k| self.gen(k) }
@@ -530,6 +547,9 @@ module TBD
530
547
  h[:roof ] = @set[id].key?(:roof)
531
548
  h[:roofconcave ] = @set[id].key?(:roofconcave)
532
549
  h[:roofconvex ] = @set[id].key?(:roofconvex)
550
+ h[:ceiling ] = @set[id].key?(:ceiling)
551
+ h[:ceilingconcave ] = @set[id].key?(:ceilingconcave)
552
+ h[:ceilingconvex ] = @set[id].key?(:ceilingconvex)
533
553
  h[:grade ] = @set[id].key?(:grade)
534
554
  h[:gradeconcave ] = @set[id].key?(:gradeconcave)
535
555
  h[:gradeconvex ] = @set[id].key?(:gradeconvex)
@@ -562,6 +582,7 @@ module TBD
562
582
  v[:corner ] = 0; v[:cornerconcave ] = 0; v[:cornerconvex ] = 0
563
583
  v[:parapet ] = 0; v[:parapetconcave ] = 0; v[:parapetconvex ] = 0
564
584
  v[:roof ] = 0; v[:roofconcave ] = 0; v[:roofconvex ] = 0
585
+ v[:ceiling ] = 0; v[:ceilingconcave ] = 0; v[:ceilingconvex ] = 0
565
586
  v[:party ] = 0; v[:partyconcave ] = 0; v[:partyconvex ] = 0
566
587
  v[:grade ] = 0; v[:gradeconcave ] = 0; v[:gradeconvex ] = 0
567
588
  v[:balcony ] = 0; v[:balconyconcave ] = 0; v[:balconyconvex ] = 0
@@ -697,6 +718,11 @@ module TBD
697
718
  v[:roofconvex ] = @set[id][:roof ] if h[:roof ]
698
719
  v[:roofconcave ] = @set[id][:roofconcave ] if h[:roofconcave ]
699
720
  v[:roofconvex ] = @set[id][:roofconvex ] if h[:roofconvex ]
721
+ v[:ceiling ] = @set[id][:ceiling ] if h[:ceiling ]
722
+ v[:ceilingconcave ] = @set[id][:ceiling ] if h[:ceiling ]
723
+ v[:ceilingconvex ] = @set[id][:ceiling ] if h[:ceiling ]
724
+ v[:ceilingconcave ] = @set[id][:ceilingconcave ] if h[:ceilingconcave ]
725
+ v[:ceilingconvex ] = @set[id][:ceilingconvex ] if h[:ceilingconvex ]
700
726
  v[:party ] = @set[id][:party ] if h[:party ]
701
727
  v[:partyconcave ] = @set[id][:party ] if h[:party ]
702
728
  v[:partyconvex ] = @set[id][:party ] if h[:party ]
@@ -764,6 +790,7 @@ module TBD
764
790
 
765
791
  max = [v[:roofconcave], v[:roofconvex]].max
766
792
  v[:roof] = max unless @has[:roof]
793
+
767
794
  @val[id] = v
768
795
 
769
796
  true
@@ -783,6 +810,9 @@ module TBD
783
810
  # @option set [#to_f] :roof roof-to-wall intersection
784
811
  # @option set [#to_f] :roofconcave basilaire variant
785
812
  # @option set [#to_f] :roofconvex typical
813
+ # @option set [#to_f] :ceiling intermediate (uninsulated) ceiling perimeter
814
+ # @option set [#to_f] :ceilingconcave cantilever variant
815
+ # @option set [#to_f] :ceilingconvex colonnade variant
786
816
  # @option set [#to_f] :fenestration head/sill/jamb interface
787
817
  # @option set [#to_f] :head (fenestrated) header interface
788
818
  # @option set [#to_f] :headconcave (fenestrated) basilaire variant
@@ -870,6 +900,9 @@ module TBD
870
900
  s[:roof ] = set[:roof ] if set.key?(:roof)
871
901
  s[:roofconcave ] = set[:roofconcave ] if set.key?(:roofconcave)
872
902
  s[:roofconvex ] = set[:roofconvex ] if set.key?(:roofconvex)
903
+ s[:ceiling ] = set[:ceiling ] if set.key?(:ceiling)
904
+ s[:ceilingconcave ] = set[:ceilingconcave ] if set.key?(:ceilingconcave)
905
+ s[:ceilingconvex ] = set[:ceilingconvex ] if set.key?(:ceilingconvex)
873
906
  s[:fenestration ] = set[:fenestration ] if set.key?(:fenestration)
874
907
  s[:head ] = set[:head ] if set.key?(:head)
875
908
  s[:headconcave ] = set[:headconcave ] if set.key?(:headconcave)
@@ -926,6 +959,7 @@ module TBD
926
959
 
927
960
  s[:joint ] = 0.000 unless set.key?(:joint)
928
961
  s[:transition ] = 0.000 unless set.key?(:transition)
962
+ s[:ceiling ] = 0.000 unless set.key?(:ceiling)
929
963
 
930
964
  @set[id] = s
931
965
  self.gen(id)
@@ -941,13 +975,13 @@ module TBD
941
975
  #
942
976
  # @param id [#to_s] PSI set identifier
943
977
  # @example intermediate floor slab intersection
944
- # shorthands("A901")
978
+ # shorthands("90.1.22|steel.m|default")
945
979
  #
946
980
  # @return [Hash] has: Hash (Bool), val: Hash (PSI factors) see logs if empty
947
981
  def shorthands(id = "")
948
982
  mth = "TBD::#{__callee__}"
949
983
  sh = { has: {}, val: {} }
950
- id = trim(id)
984
+ id = trim(id)
951
985
  return mismatch("set ID", id, String, mth, ERR, a) if id.empty?
952
986
  return hashkey(id, @set , id, mth, ERR, sh) unless @set.key?(id)
953
987
  return hashkey(id, @has , id, mth, ERR, sh) unless @has.key?(id)
@@ -969,7 +1003,7 @@ module TBD
969
1003
  def complete?(id = "")
970
1004
  mth = "TBD::#{__callee__}"
971
1005
  a = false
972
- id = trim(id)
1006
+ id = trim(id)
973
1007
  return mismatch("set ID", id, String, mth, ERR, a) if id.empty?
974
1008
  return hashkey(id, @set , id, mth, ERR, a) unless @set.key?(id)
975
1009
  return hashkey(id, @has , id, mth, ERR, a) unless @has.key?(id)
@@ -1853,9 +1887,6 @@ module TBD
1853
1887
 
1854
1888
  # Evaluate current set content before processing a new linked surface.
1855
1889
  is = {}
1856
- is[:head ] = set.keys.to_s.include?("head")
1857
- is[:sill ] = set.keys.to_s.include?("sill")
1858
- is[:jamb ] = set.keys.to_s.include?("jamb")
1859
1890
  is[:doorhead ] = set.keys.to_s.include?("doorhead")
1860
1891
  is[:doorsill ] = set.keys.to_s.include?("doorsill")
1861
1892
  is[:doorjamb ] = set.keys.to_s.include?("doorjamb")
@@ -1866,6 +1897,7 @@ module TBD
1866
1897
  is[:corner ] = set.keys.to_s.include?("corner")
1867
1898
  is[:parapet ] = set.keys.to_s.include?("parapet")
1868
1899
  is[:roof ] = set.keys.to_s.include?("roof")
1900
+ is[:ceiling ] = set.keys.to_s.include?("ceiling")
1869
1901
  is[:party ] = set.keys.to_s.include?("party")
1870
1902
  is[:grade ] = set.keys.to_s.include?("grade")
1871
1903
  is[:balcony ] = set.keys.to_s.include?("balcony")
@@ -1873,6 +1905,12 @@ module TBD
1873
1905
  is[:balconydoorsill ] = set.keys.to_s.include?("balconydoorsill")
1874
1906
  is[:rimjoist ] = set.keys.to_s.include?("rimjoist")
1875
1907
 
1908
+ if is.empty?
1909
+ is[:head] = set.keys.to_s.include?("head")
1910
+ is[:sill] = set.keys.to_s.include?("sill")
1911
+ is[:jamb] = set.keys.to_s.include?("jamb")
1912
+ end
1913
+
1876
1914
  # Label edge as ...
1877
1915
  # :head, :sill, :jamb (vertical fenestration)
1878
1916
  # :doorhead, :doorsill, :doorjamb (opaque door)
@@ -2092,6 +2130,41 @@ module TBD
2092
2130
  is[:corner ] = true
2093
2131
  end
2094
2132
 
2133
+ # Label edge as :ceiling if linked to:
2134
+ # +1 deratable surfaces
2135
+ # 1x underatable CONDITIONED floor linked to an unoccupied space
2136
+ # 1x adjacent CONDITIONED ceiling linked to an occupied space
2137
+ edge[:surfaces].keys.each do |i|
2138
+ break if is[:ceiling]
2139
+ break unless deratables.size > 0
2140
+ break if floors.key?(id)
2141
+ next if i == id
2142
+ next unless floors.key?(i)
2143
+ next if floors[i][:ground ]
2144
+ next unless floors[i][:conditioned]
2145
+ next if floors[i][:occupied ]
2146
+
2147
+ ceiling = floors[i][:boundary]
2148
+ next unless ceilings.key?(ceiling)
2149
+ next unless ceilings[ceiling][:conditioned]
2150
+ next unless ceilings[ceiling][:occupied ]
2151
+
2152
+ other = deratables.first unless deratables.first == id
2153
+ other = deratables.last unless deratables.last == id
2154
+ other = id if deratables.size == 1
2155
+
2156
+ s1 = edge[:surfaces][id]
2157
+ s2 = edge[:surfaces][other]
2158
+ concave = concave?(s1, s2)
2159
+ convex = convex?(s1, s2)
2160
+ flat = !concave && !convex
2161
+
2162
+ set[:ceiling ] = shorts[:val][:ceiling ] if flat
2163
+ set[:ceilingconcave] = shorts[:val][:ceilingconcave] if concave
2164
+ set[:ceilingconvex ] = shorts[:val][:ceilingconvex ] if convex
2165
+ is[:ceiling ] = true
2166
+ end
2167
+
2095
2168
  # Label edge as :parapet/:roof if linked to:
2096
2169
  # 1x deratable wall
2097
2170
  # 1x deratable ceiling
@@ -2172,22 +2245,23 @@ module TBD
2172
2245
  is[:grade ] = true
2173
2246
  end
2174
2247
 
2175
- # Label edge as :rimjoist, :balcony, :balconysill or :balconydoorsill if linked to:
2248
+ # Label edge as :rimjoist, :balcony, :balconysill or :balconydoorsill,
2249
+ # if linked to:
2176
2250
  # 1x deratable surface
2177
2251
  # 1x CONDITIONED floor
2178
2252
  # 1x shade (optional)
2179
2253
  # 1x subsurface (optional)
2180
- #
2181
- # Despite referring to 'sill' or 'doorsill', a 'balconysill' or
2182
- # 'balconydoorsill' edge may instead link (rarer) cases of balcony and a
2183
- # fenestratio/door head. ASHRAE 90.1 2022 does not make the distinction
2184
- # between sill vs head when intermediatre floor, balcony and vertical
2185
- # fenestration meet. 'Sills' are simply the most common occurrence.
2186
2254
  balcony = false
2187
2255
  balconysill = false # vertical fenestration
2188
2256
  balconydoorsill = false # opaque door
2189
2257
 
2258
+ # Despite referring to 'sill' or 'doorsill', a 'balconysill' or
2259
+ # 'balconydoorsill' edge may instead link (rarer) cases of balcony and a
2260
+ # fenestration/door head. ASHRAE 90.1 2022 does not make the distinction
2261
+ # between sill vs head when intermediate floor, balcony and vertical
2262
+ # fenestration meet. 'Sills' are simply the most common occurrence.
2190
2263
  edge[:surfaces].keys.each do |i|
2264
+ break if is[:ceiling]
2191
2265
  break if balcony
2192
2266
  next if i == id
2193
2267
 
@@ -2259,15 +2333,17 @@ module TBD
2259
2333
  end
2260
2334
 
2261
2335
  edge[:surfaces].keys.each do |i|
2262
- break if is[:rimjoist ] || is[:balcony ] ||
2263
- is[:balconysill] || is[:balconydoorsill]
2336
+ break if is[:ceiling ]
2337
+ break if is[:rimjoist ]
2338
+ break if is[:balcony ]
2339
+ break if is[:balconysill ]
2340
+ break if is[:balconydoorsill]
2264
2341
  break unless deratables.size > 0
2265
2342
  break if floors.key?(id)
2266
2343
  next if i == id
2267
2344
  next unless floors.key?(i)
2268
- next unless floors[i].key?(:conditioned)
2269
- next unless floors[i][:conditioned]
2270
2345
  next if floors[i][:ground ]
2346
+ next unless floors[i][:conditioned]
2271
2347
 
2272
2348
  other = deratables.first unless deratables.first == id
2273
2349
  other = deratables.last unless deratables.last == id
data/lib/tbd/ua.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
  #
3
- # Copyright (c) 2020-2023 Denis Bourgeois & Dan Macumber
3
+ # Copyright (c) 2020-2024 Denis Bourgeois & Dan Macumber
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -1000,7 +1000,7 @@ module TBD
1000
1000
  model = "* modèle : #{ua[:file]}" if ua.key?(:file) && lang == :fr
1001
1001
  model += " (v#{ua[:version]})" if ua.key?(:version)
1002
1002
  report << model unless model.empty?
1003
- report << "* TBD : v3.3.0"
1003
+ report << "* TBD : v3.4.0"
1004
1004
  report << "* date : #{ua[:date]}"
1005
1005
 
1006
1006
  if lang == :en
data/lib/tbd/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
  #
3
- # Copyright (c) 2020-2023 Denis Bourgeois & Dan Macumber
3
+ # Copyright (c) 2020-2024 Denis Bourgeois & Dan Macumber
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -21,5 +21,5 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  module TBD
24
- VERSION = "3.3.0".freeze # TBD release version
24
+ VERSION = "3.4.0".freeze # TBD release version
25
25
  end
data/lib/tbd.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
  #
3
- # Copyright (c) 2020-2023 Denis Bourgeois & Dan Macumber
3
+ # Copyright (c) 2020-2024 Denis Bourgeois & Dan Macumber
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
data/tbd.schema.json CHANGED
@@ -122,6 +122,18 @@
122
122
  "title": "Convex (other than parapet/overhang) roof/wall edge PSI",
123
123
  "type": "number"
124
124
  },
125
+ "ceiling": {
126
+ "title": "Intermediate ceiling (not floor) edge PSI",
127
+ "type": "number"
128
+ },
129
+ "ceilingconcave": {
130
+ "title": "Concave intermediate ceiling (not floor) edge PSI",
131
+ "type": "number"
132
+ },
133
+ "ceilingconvex": {
134
+ "title": "Convex intermediate ceiling (not floor) edge PSI",
135
+ "type": "number"
136
+ },
125
137
  "fenestration": {
126
138
  "title": "Window or glazed door perimeter PSI",
127
139
  "type": "number"
@@ -369,6 +381,9 @@
369
381
  "roof",
370
382
  "roofconcave",
371
383
  "roofconvex",
384
+ "ceiling",
385
+ "ceilingconcave",
386
+ "ceilingconvex",
372
387
  "fenestration",
373
388
  "head",
374
389
  "headconcave",
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tbd
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.0
4
+ version: 3.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Denis Bourgeois & Dan Macumber
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-22 00:00:00.000000000 Z
11
+ date: 2024-01-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: topolys
@@ -133,6 +133,7 @@ files:
133
133
  - json/tbd_warehouse17.json
134
134
  - json/tbd_warehouse18.json
135
135
  - json/tbd_warehouse4.json
136
+ - json/tbd_z5.json
136
137
  - lib/measures/tbd/LICENSE.md
137
138
  - lib/measures/tbd/README.md
138
139
  - lib/measures/tbd/README.md.erb
@@ -165,7 +166,7 @@ licenses:
165
166
  - MIT
166
167
  metadata:
167
168
  homepage_uri: https://github.com/rd2/tbd
168
- source_code_uri: https://github.com/rd2/tbd/tree/v3.3.0
169
+ source_code_uri: https://github.com/rd2/tbd/tree/v3.4.0
169
170
  bug_tracker_uri: https://github.com/rd2/tbd/issues
170
171
  post_install_message:
171
172
  rdoc_options: []