lib/measures/tbd/resources/psi.rb
def generateKiva(model, walls, floors, edges)
  unless model && walls && floors && edges
    TBD.log(TBD::DEBUG,
      "Invalid OpenStudio model, can't generate KIVA inputs - skipping")
    return false
  end
  cl = OpenStudio::Model::Model
  cl2 = model.class
  unless model.is_a?(cl)
    TBD.log(TBD::DEBUG,
      "#{cl2}? expected #{cl}, can't generate KIVA inputs - skipping")
    return false
  end
  cl2 = walls.class
  unless walls.is_a?(Hash)
    TBD.log(TBD::DEBUG,
      "#{cl2}? expected walls Hash, can't generate KIVA inputs - skipping")
    return false
  end
  cl2 = floors.class
  unless floors.is_a?(Hash)
    TBD.log(TBD::DEBUG,
      "#{cl2}? expected floors Hash, can't generate KIVA inputs - skipping")
    return false
  end
  cl2 = edges.class
  unless edges.is_a?(Hash)
    TBD.log(TBD::DEBUG,
      "#{cl2}? expected edges Hash, can't generate KIVA inputs - skipping")
    return false
  end

  # Strictly rely on Kiva's total exposed perimeter approach.
  arg = "TotalExposedPerimeter"
  kiva = true

  # The following is loosely adapted from:
  # github.com/NREL/OpenStudio-resources/blob/develop/model/simulationtests/
  # foundation_kiva.rb ... thanks.

  # Generate template for KIVA settings. This is usually not required (the
  # default KIVA settings are fine), but its explicit inclusion in the OSM
  # does offer users easy access to further (manually) tweak settings e.g.,
  # soil properties if required. Initial tests show slight differences in
  # simulation results w/w/o explcit inclusion of the KIVA settings template
  # in the OSM. TO-DO: Check in.idf vs in.osm for any deviation from default
  # values as specified in the IO Reference Manual.
  foundation_kiva_settings = model.getFoundationKivaSettings

  # One way to expose in-built default parameters (in the future), e.g.:
  # soil_k = foundation_kiva_settings.soilConductivity
  # foundation_kiva_settings.setSoilConductivity(soil_k)

  # Generic 1" XPS insulation (for slab-on-grade setup) - unused if basement.
  xps25mm = OpenStudio::Model::StandardOpaqueMaterial.new(model)
  xps25mm.setRoughness("Rough")
  xps25mm.setThickness(0.0254)
  xps25mm.setConductivity(0.029)
  xps25mm.setDensity(28)
  xps25mm.setSpecificHeat(1450)
  xps25mm.setThermalAbsorptance(0.9)
  xps25mm.setSolarAbsorptance(0.7)

  # Tag foundation-facing floors, then walls.
  edges.values.each do |edge|
    edge[:surfaces].keys.each do |id|

      # Start by processing edge-linked foundation-facing floors.
      next unless floors.has_key?(id)
      next unless floors[id][:boundary].downcase == "foundation"

      # By default, foundation floors are initially slabs-on-grade.
      floors[id][:kiva] = :slab

      # Re(tag) floors as basements if foundation-facing walls.
      edge[:surfaces].keys.each do |i|
        next unless walls.has_key?(i)
        next unless walls[i][:boundary].downcase == "foundation"
        next if walls[i].has_key?(:kiva)

        # (Re)tag as :basement if edge-linked foundation walls.
        floors[id][:kiva] = :basement
        walls[i][:kiva] = id
      end
    end
  end

  # Fetch exposed perimeters.
  edges.values.each do |edge|
    edge[:surfaces].keys.each do |id|
      next unless floors.has_key?(id)
      next unless floors[id].has_key?(:kiva)

      # Initialize if first iteration.
      floors[id][:exposed] = 0.0 unless floors[id].has_key?(:exposed)

      edge[:surfaces].keys.each do |i|
        next unless walls.has_key?(i)
        b = walls[i][:boundary].downcase
        next unless b == "outdoors"
        floors[id][:exposed] += edge[:length]
      end
    end
  end

  # Generate unique Kiva foundation per foundation-facing floor.
  edges.values.each do |edge|
    edge[:surfaces].keys.each do |id|
      next unless floors.has_key?(id)
      next unless floors[id].has_key?(:kiva)
      next if floors[id].has_key?(:foundation)

      floors[id][:foundation] = OpenStudio::Model::FoundationKiva.new(model)

      # It's assumed that generated foundation walls have insulated
      # constructions. Perimeter insulation for slabs-on-grade.
      # Typical circa-1980 slab-on-grade (perimeter) insulation setup.
      if floors[id][:kiva] == :slab
        floors[id][:foundation].setInteriorHorizontalInsulationMaterial(xps25mm)
        floors[id][:foundation].setInteriorHorizontalInsulationWidth(0.6)
      end

      # Locate OSM surface and assign Kiva foundation & perimeter objects.
      found = false
      model.getSurfaces.each do |s|
        next unless s.nameString == id
        next unless s.outsideBoundaryCondition.downcase == "foundation"
        found = true

        # Retrieve surface (standard) construction (which may be defaulted)
        # before assigning a Kiva Foundation object to the surface. Then
        # reassign the construction (no longer defaulted).
        construction = s.construction.get
        s.setAdjacentFoundation(floors[id][:foundation])
        s.setConstruction(construction)

        # Generate surface's Kiva exposed perimeter object.
        exp = floors[id][:exposed]
        #exp = TOL if exp < TOL
        perimeter = s.createSurfacePropertyExposedFoundationPerimeter(arg, exp)

        # The following 5x lines are a (temporary?) fix for exposed perimeter
        # lengths of 0m - a perfectly valid entry in an IDF (e.g. "core" slab).
        # Unfortunately OpenStudio (currently) rejects 0 as an inclusive minimum
        # value. So despite passing a valid 0 "exp" argument, OpenStudio does
        # not initialize the "TotalExposedPerimeter" entry. Compare relevant
        # EnergyPlus vs OpenStudio .idd entries.

        # The fix: if a valid Kiva exposed perimeter is equal or less than 1mm,
        # fetch the perimeter object and attempt to explicitely set the exposed
        # perimeter length to 0m. If unsuccessful (situation remains unfixed),
        # then set to 1mm. Simulations results should be virtually identical.
        unless exp > 0.001 || perimeter.empty?
          perimeter = perimeter.get
          success = perimeter.setTotalExposedPerimeter(0)
          perimeter.setTotalExposedPerimeter(0.001) unless success
        end

      end
      kiva = false unless found
    end
  end

  # Link foundation walls to right Kiva foundation objects (if applicable).
  edges.values.each do |edge|
    edge[:surfaces].keys.each do |i|
      next unless walls.has_key?(i)
      next unless walls[i].has_key?(:kiva)
      id = walls[i][:kiva]
      next unless floors.has_key?(id)
      next unless floors[id].has_key?(:foundation)

      # Locate OSM wall.
      model.getSurfaces.each do |s|
        next unless s.nameString == i
        s.setAdjacentFoundation(floors[id][:foundation])
        s.setConstruction(s.construction.get)
      end
    end
  end
  kiva
end
##
# Generate OSM Kiva settings and objects if model surfaces have 'foundation'
# boundary conditions.
#
# @param [OpenStudio::Model::Model] model An OS model
# @param [Hash] floors TBD-generated floors
# @param [Hash] walls TBD-generated walls
# @param [Hash] edges TBD-generated edges (many linking floors & walls
#
# @return [Bool] Returns true if Kiva foundations are successfully generated.
Generate OSM Kiva settings and objects if model surfaces have 'foundation'
boundary conditions.
Generate OSM Kiva settings and objects if model surfaces have ' foundation ' boundary conditions .
def generateKiva(model, walls, floors, edges)
  unless model && walls && floors && edges
    TBD.log(TBD::DEBUG,
      "Invalid OpenStudio model, can't generate KIVA inputs - skipping")
    return false
  end
  cl = OpenStudio::Model::Model
  cl2 = model.class
  unless model.is_a?(cl)
    TBD.log(TBD::DEBUG,
      "#{cl2}? expected #{cl}, can't generate KIVA inputs - skipping")
    return false
  end
  cl2 = walls.class
  unless walls.is_a?(Hash)
    TBD.log(TBD::DEBUG,
      "#{cl2}? expected walls Hash, can't generate KIVA inputs - skipping")
    return false
  end
  cl2 = floors.class
  unless floors.is_a?(Hash)
    TBD.log(TBD::DEBUG,
      "#{cl2}? expected floors Hash, can't generate KIVA inputs - skipping")
    return false
  end
  cl2 = edges.class
  unless edges.is_a?(Hash)
    TBD.log(TBD::DEBUG,
      "#{cl2}? expected edges Hash, can't generate KIVA inputs - skipping")
    return false
  end
  arg = "TotalExposedPerimeter"
  kiva = true
  foundation_kiva_settings = model.getFoundationKivaSettings
  xps25mm = OpenStudio::Model::StandardOpaqueMaterial.new(model)
  xps25mm.setRoughness("Rough")
  xps25mm.setThickness(0.0254)
  xps25mm.setConductivity(0.029)
  xps25mm.setDensity(28)
  xps25mm.setSpecificHeat(1450)
  xps25mm.setThermalAbsorptance(0.9)
  xps25mm.setSolarAbsorptance(0.7)
  edges.values.each do |edge|
    edge[:surfaces].keys.each do |id|
      next unless floors.has_key?(id)
      next unless floors[id][:boundary].downcase == "foundation"
      floors[id][:kiva] = :slab
      edge[:surfaces].keys.each do |i|
        next unless walls.has_key?(i)
        next unless walls[i][:boundary].downcase == "foundation"
        next if walls[i].has_key?(:kiva)
        floors[id][:kiva] = :basement
        walls[i][:kiva] = id
      end
    end
  end
  edges.values.each do |edge|
    edge[:surfaces].keys.each do |id|
      next unless floors.has_key?(id)
      next unless floors[id].has_key?(:kiva)
      floors[id][:exposed] = 0.0 unless floors[id].has_key?(:exposed)
      edge[:surfaces].keys.each do |i|
        next unless walls.has_key?(i)
        b = walls[i][:boundary].downcase
        next unless b == "outdoors"
        floors[id][:exposed] += edge[:length]
      end
    end
  end
  edges.values.each do |edge|
    edge[:surfaces].keys.each do |id|
      next unless floors.has_key?(id)
      next unless floors[id].has_key?(:kiva)
      next if floors[id].has_key?(:foundation)
      floors[id][:foundation] = OpenStudio::Model::FoundationKiva.new(model)
      if floors[id][:kiva] == :slab
        floors[id][:foundation].setInteriorHorizontalInsulationMaterial(xps25mm)
        floors[id][:foundation].setInteriorHorizontalInsulationWidth(0.6)
      end
      found = false
      model.getSurfaces.each do |s|
        next unless s.nameString == id
        next unless s.outsideBoundaryCondition.downcase == "foundation"
        found = true
        construction = s.construction.get
        s.setAdjacentFoundation(floors[id][:foundation])
        s.setConstruction(construction)
        exp = floors[id][:exposed]
        perimeter = s.createSurfacePropertyExposedFoundationPerimeter(arg, exp)
        unless exp > 0.001 || perimeter.empty?
          perimeter = perimeter.get
          success = perimeter.setTotalExposedPerimeter(0)
          perimeter.setTotalExposedPerimeter(0.001) unless success
        end
      end
      kiva = false unless found
    end
  end
  edges.values.each do |edge|
    edge[:surfaces].keys.each do |i|
      next unless walls.has_key?(i)
      next unless walls[i].has_key?(:kiva)
      id = walls[i][:kiva]
      next unless floors.has_key?(id)
      next unless floors[id].has_key?(:foundation)
      model.getSurfaces.each do |s|
        next unless s.nameString == i
        s.setAdjacentFoundation(floors[id][:foundation])
        s.setConstruction(s.construction.get)
      end
    end
  end
  kiva
end
def generateKiva ( model , walls , floors , edges ) unless model && walls && floors && edges TBD . log ( TBD :: DEBUG , "Invalid OpenStudio model, can't generate KIVA inputs - skipping" ) return false end cl = OpenStudio :: Model :: Model cl2 = model . class unless model . is_a? ( cl ) TBD . log ( TBD :: DEBUG , "#{cl2}? expected #{cl}, can't generate KIVA inputs - skipping" ) return false end cl2 = walls . class unless walls . is_a? ( Hash ) TBD . log ( TBD :: DEBUG , "#{cl2}? expected walls Hash, can't generate KIVA inputs - skipping" ) return false end cl2 = floors . class unless floors . is_a? ( Hash ) TBD . log ( TBD :: DEBUG , "#{cl2}? expected floors Hash, can't generate KIVA inputs - skipping" ) return false end cl2 = edges . class unless edges . is_a? ( Hash ) TBD . log ( TBD :: DEBUG , "#{cl2}? expected edges Hash, can't generate KIVA inputs - skipping" ) return false end arg = "TotalExposedPerimeter" kiva = true foundation_kiva_settings = model . getFoundationKivaSettings xps25mm = OpenStudio :: Model :: StandardOpaqueMaterial . new ( model ) xps25mm . setRoughness ( "Rough" ) xps25mm . setThickness ( 0.0254 ) xps25mm . setConductivity ( 0.029 ) xps25mm . setDensity ( 28 ) xps25mm . setSpecificHeat ( 1450 ) xps25mm . setThermalAbsorptance ( 0.9 ) xps25mm . setSolarAbsorptance ( 0.7 ) edges . values . each do | edge | edge [ :surfaces ] . keys . each do | id | next unless floors . has_key? ( id ) next unless floors [ id ] [ :boundary ] . downcase == "foundation" floors [ id ] [ :kiva ] = :slab edge [ :surfaces ] . keys . each do | i | next unless walls . has_key? ( i ) next unless walls [ i ] [ :boundary ] . downcase == "foundation" next if walls [ i ] . has_key? ( :kiva ) floors [ id ] [ :kiva ] = :basement walls [ i ] [ :kiva ] = id end end end edges . values . each do | edge | edge [ :surfaces ] . keys . each do | id | next unless floors . has_key? ( id ) next unless floors [ id ] . has_key? ( :kiva ) floors [ id ] [ :exposed ] = 0.0 unless floors [ id ] . has_key? ( :exposed ) edge [ :surfaces ] . keys . each do | i | next unless walls . has_key? ( i ) b = walls [ i ] [ :boundary ] . downcase next unless b == "outdoors" floors [ id ] [ :exposed ] += edge [ :length ] end end end edges . values . each do | edge | edge [ :surfaces ] . keys . each do | id | next unless floors . has_key? ( id ) next unless floors [ id ] . has_key? ( :kiva ) next if floors [ id ] . has_key? ( :foundation ) floors [ id ] [ :foundation ] = OpenStudio :: Model :: FoundationKiva . new ( model ) if floors [ id ] [ :kiva ] == :slab floors [ id ] [ :foundation ] . setInteriorHorizontalInsulationMaterial ( xps25mm ) floors [ id ] [ :foundation ] . setInteriorHorizontalInsulationWidth ( 0.6 ) end found = false model . getSurfaces . each do | s | next unless s . nameString == id next unless s . outsideBoundaryCondition . downcase == "foundation" found = true construction = s . construction . get s . setAdjacentFoundation ( floors [ id ] [ :foundation ] ) s . setConstruction ( construction ) exp = floors [ id ] [ :exposed ] perimeter = s . createSurfacePropertyExposedFoundationPerimeter ( arg , exp ) unless exp > 0.001 || perimeter . empty? perimeter = perimeter . get success = perimeter . setTotalExposedPerimeter ( 0 ) perimeter . setTotalExposedPerimeter ( 0.001 ) unless success end end kiva = false unless found end end edges . values . each do | edge | edge [ :surfaces ] . keys . each do | i | next unless walls . has_key? ( i ) next unless walls [ i ] . has_key? ( :kiva ) id = walls [ i ] [ :kiva ] next unless floors . has_key? ( id ) next unless floors [ id ] . has_key? ( :foundation ) model . getSurfaces . each do | s | next unless s . nameString == i s . setAdjacentFoundation ( floors [ id ] [ :foundation ] ) s . setConstruction ( s . construction . get ) end end end kiva end
Generate OSM Kiva settings and objects if model surfaces have 'foundation'
boundary conditions.
Generate OSM Kiva settings and objects if model surfaces have ' foundation ' boundary conditions .
# Strictly rely on Kiva's total exposed perimeter approach. # The following is loosely adapted from: # github.com/NREL/OpenStudio-resources/blob/develop/model/simulationtests/ # foundation_kiva.rb ... thanks. # Generate template for KIVA settings. This is usually not required (the # default KIVA settings are fine), but its explicit inclusion in the OSM # does offer users easy access to further (manually) tweak settings e.g., # soil properties if required. Initial tests show slight differences in # simulation results w/w/o explcit inclusion of the KIVA settings template # in the OSM. TO-DO: Check in.idf vs in.osm for any deviation from default # values as specified in the IO Reference Manual. # One way to expose in-built default parameters (in the future), e.g.: # soil_k = foundation_kiva_settings.soilConductivity # foundation_kiva_settings.setSoilConductivity(soil_k) # Generic 1" XPS insulation (for slab-on-grade setup) - unused if basement. # Tag foundation-facing floors, then walls. # Start by processing edge-linked foundation-facing floors. # By default, foundation floors are initially slabs-on-grade. # Re(tag) floors as basements if foundation-facing walls. # (Re)tag as :basement if edge-linked foundation walls. # Fetch exposed perimeters. # Initialize if first iteration. # Generate unique Kiva foundation per foundation-facing floor. # It's assumed that generated foundation walls have insulated # constructions. Perimeter insulation for slabs-on-grade. # Typical circa-1980 slab-on-grade (perimeter) insulation setup. # Locate OSM surface and assign Kiva foundation & perimeter objects. # Retrieve surface (standard) construction (which may be defaulted) # before assigning a Kiva Foundation object to the surface. Then # reassign the construction (no longer defaulted). # Generate surface's Kiva exposed perimeter object. #exp = TOL if exp < TOL # The following 5x lines are a (temporary?) fix for exposed perimeter # lengths of 0m - a perfectly valid entry in an IDF (e.g. "core" slab). # Unfortunately OpenStudio (currently) rejects 0 as an inclusive minimum # value. So despite passing a valid 0 "exp" argument, OpenStudio does # not initialize the "TotalExposedPerimeter" entry. Compare relevant # EnergyPlus vs OpenStudio .idd entries. # The fix: if a valid Kiva exposed perimeter is equal or less than 1mm, # fetch the perimeter object and attempt to explicitely set the exposed # perimeter length to 0m. If unsuccessful (situation remains unfixed), # then set to 1mm. Simulations results should be virtually identical. # Link foundation walls to right Kiva foundation objects (if applicable). # Locate OSM wall.
Returns true if Kiva foundations are successfully generated.
Returns true if Kiva foundations are successfully generated .
Bool
model
walls
floors
edges
edges TBD-generated edges (many linking floors & walls
edges TBD - generated edges ( many linking floors & walls