tbd 3.3.0 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []