@@ -866,8 +866,8 @@ def self.process_load_floors(zone_loads, weather)
866866 next unless slab . is_thermal_boundary
867867
868868 if slab . interior_adjacent_to == HPXML ::LocationLivingSpace # Slab-on-grade
869- floor_ufactor = 0.1 # FIXME: Hard-coded
870- zone_loads . Heat_Floors += floor_ufactor * slab . area * ( @heat_setpoint - weather . data . GroundMonthlyTemps [ 0 ] )
869+ f_value = calc_slab_f_value ( slab )
870+ zone_loads . Heat_Floors += f_value * slab . exposed_perimeter * @htd
871871 elsif slab . interior_adjacent_to == HPXML ::LocationBasementConditioned
872872 # Based on MJ 8th Ed. A12-7 and ASHRAE HoF 2013 pg 18.31 Eq 40
873873 # FIXME: Assumes slab is uninsulated?
@@ -2980,6 +2980,70 @@ def self.get_foundation_wall_properties(foundation_wall)
29802980 return u_wall_with_soil , u_wall_without_soil
29812981 end
29822982
2983+ def self . calc_slab_f_value ( slab )
2984+ # Calculation for the F-values in Table 4A for slab foundations.
2985+ # Important pages are the Table values (pg. 344-345) and the software protocols
2986+ # in Appendix 12 (pg. 517-518).
2987+ ins_rvalue = slab . under_slab_insulation_r_value + slab . perimeter_insulation_r_value
2988+ ins_rvalue_edge = slab . perimeter_insulation_r_value
2989+ edge_ins_rvalue =
2990+ if slab . under_slab_insulation_spans_entire_slab
2991+ ins_length = 1000.0
2992+ else
2993+ ins_length = 0
2994+ if slab . under_slab_insulation_r_value > 0
2995+ ins_length += slab . under_slab_insulation_width
2996+ end
2997+ if slab . perimeter_insulation_r_value > 0
2998+ ins_length += slab . perimeter_insulation_depth
2999+ end
3000+ end
3001+
3002+ soil_r_per_foot = Material . Soil ( 12.0 ) . rvalue
3003+ slab_r_gravel_per_inch = 0.65 # Based on calibration by Tony Fontanini
3004+
3005+ # Because of uncertainty pertaining to the effective path radius, F-values are calculated
3006+ # for six radii (8, 9, 10, 11, 12, and 13 feet) and averaged.
3007+ f_values = [ ]
3008+ for path_radius in 8 ..13
3009+ u_effective = [ ]
3010+ for radius in 0 ..path_radius
3011+ spl = [ Math ::PI * radius - 1 , 0 ] . max # soil path length (SPL)
3012+
3013+ # Concrete, gravel, and insulation
3014+ if radius == 0
3015+ r_concrete = 0.0
3016+ r_gravel = 0.0 # No gravel on edge
3017+ r_ins = ins_rvalue_edge
3018+ else
3019+ r_concrete = Material . Concrete ( slab . thickness ) . rvalue
3020+ r_gravel = [ slab_r_gravel_per_inch * ( 12.0 - slab . thickness ) , 0 ] . max
3021+ if radius <= ins_length
3022+ r_ins = ins_rvalue
3023+ else
3024+ r_ins = 0.0
3025+ end
3026+ end
3027+
3028+ # Air Films = Indoor Finish + Indoor Air Film + Exposed Air Film (Figure A12-6 pg. 517)
3029+ r_air_film = 0.05 + 0.92 + 0.17
3030+
3031+ # Soil
3032+ r_soil = soil_r_per_foot * spl # (h-F-ft2/BTU)
3033+
3034+ # Effective R-Value
3035+ r_air_to_air = r_concrete + r_gravel + r_ins + r_air_film + r_soil
3036+
3037+ # Effective U-Factor
3038+ u_effective << 1.0 / r_air_to_air
3039+ end
3040+
3041+ f_values << u_effective . inject ( 0 , :+ ) # sum array
3042+ end
3043+
3044+ return f_values . sum ( ) / f_values . size
3045+ end
3046+
29833047 def self . get_feature ( obj , feature , datatype , fail_on_error = true )
29843048 val = nil
29853049 if datatype == 'string'
0 commit comments