# # ********************************************************************* # # * Copyright (c) 2008-2015, Natural Resources Canada # # * All rights reserved. # # * # # * This library is free software; you can redistribute it and/or # # * modify it under the terms of the GNU Lesser General Public # # * License as published by the Free Software Foundation; either # # * version 2.1 of the License, or (at your option) any later version. # # * # # * This library is distributed in the hope that it will be useful, # # * but WITHOUT ANY WARRANTY; without even the implied warranty of # # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # # * Lesser General Public License for more details. # # * # # * You should have received a copy of the GNU Lesser General Public # # * License along with this library; if not, write to the Free Software # # * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # **********************************************************************/ # # # # require "singleton" # # # module BTAP # module EQuest # # Author:: Phylroy Lopez (mailto:plopez@nrcan.gc.ca) # # Copyright:: Copyright (c) NRCan # # License:: GNU Public Licence # #This class contains encapsulates the generic interface for the DOE2.x command # #set. It stores the u type, commands, and keyword pairs for each command. It also # #stores the parent and child command relationships w.r.t. the building envelope # #and the hvac systems. I have attempted to make the underlying storage of data # #private so, if required, we could move to a database solution in the future # #if required for web development.. # # class DOECommand # # # Contains the user specified name # attr_accessor :utype # #Contains the u-value # attr_accessor :uvalue # # Contains the DOE-2 command name. # attr_accessor :commandName # # Contains the Keyword Pairs. # attr_accessor :keywordPairs # # Lists all ancestors in increasing order. # attr_accessor :parents # # An Array of all the children of this command. # attr_accessor :children # # The command type. # attr_accessor :commandType # # Flag to see if this component is exempt. # attr_accessor :exempt # # Comments. To be added to the command. # attr_accessor :comments # # A list of all the non_utype_commands. # attr_accessor :non_utype_commands # # A list of all the one line commands (no keyword pairs) # attr_accessor :one_line_commands # # Pointer to the building obj. # attr_accessor :building # # # # # def remove() # #unlink children # self.children.each {|item| item.remove} # #unlink from parent. # self.get_parents[0].children.delete(self) # #remove from command array. # @building.commands.delete(self) # return self # end # # def set_parent(parent) # @parents.clear # parent.get_parents().each {|parent| @parents << parent} # @parents << parent # end # # #This method will return the value of the keyword pair if available. # #Example: # #If you object has this data in it... # # # #"EL1 West Perim Spc (G.W4)" = SPACE # #SHAPE = POLYGON # #ZONE-TYPE = CONDITIONED # #PEOPLE-SCHEDULE = "EL1 Bldg Occup Sch" # #LIGHTING-SCHEDUL = ( "EL1 Bldg InsLt Sch" ) # #EQUIP-SCHEDULE = ( "EL1 Bldg Misc Sch" ) # # # # # #then calling # # # #get_keyword_value("ZONE-TYPE") # # # #will return the string # # # #"CONDITIONED". # # # #if the keyword does not exist, it will return a nil object. # # Returns the value associated with the keyword. # def get_keyword_value(string) # return_string = String.new() # found = false # @keywordPairs.each do |pair| # if pair[0] == string # found = true # return_string = pair[1] # end # end # if found == false # raise "Error: In the command #{@utype}:#{@command_name} Attempted to get a Keyword pair #{string} present in the command\n Is this keyword missing? \n#{output}" # end # return return_string # end # # # Sets the keyword value. # def set_keyword_value(keyword, value) # found = false # unless @keywordPairs.empty? # @keywordPairs.each do |pair| # if pair[0] == keyword # pair[1] = value # found = true # end # end # if (found == false) # @keywordPairs.push([keyword,value]) # end # else # #First in the array... # add_keyword_pair(keyword,value) # end # end # # # Removes the keyword pair. # def remove_keyword_pair(string) # return_string = String.new() # @keywordPairs.each do |pair| # if pair[0] == string # @keywordPairs.delete(pair) # end # end # return return_string # end # # def initialize() # @utype = String.new() # @commandName= String.new() # @keywordPairs=Array.new() # @parents = Array.new() # @children = Array.new() # @commandType = String.new() # @exempt = false # #HVAC Hierarchry # @comments =Array.new() # @hvacLevel = Array.new() # @hvacLevel[0] =["SYSTEM"] # @hvacLevel[1] =["ZONE"] # #Envelope Hierachy # @envelopeLevel = Array.new() # @envelopeLevel[0] = ["FLOOR"] # @envelopeLevel[1] = ["SPACE"] # # @envelopeLevel[2] = [ # "EXTERIOR-WALL", # "INTERIOR-WALL", # "UNDERGROUND-WALL", # "ROOF" # ] # # @envelopeLevel[3] = [ # "WINDOW", # "DOOR"] # # @non_utype_commands = Array.new() # @non_utype_commands = [ # "TITLE", # "SITE-PARAMETERS", # "BUILD-PARAMETER", # "LOADS_REPORT", # "SYSTEMS-REPORT", # "MASTERS-METERS", # "ECONOMICS-REPORT", # "PLANT-REPORT", # "LOADS-REPORT", # "COMPLIANCE" # ] # @one_line_commands = Array.new() # @one_line_commands = ["INPUT","RUN-PERIOD","DIAGNOSTIC","ABORT", "END", "COMPUTE", "STOP", "PROJECT-DATA"] # end # # # Determines the DOE scope, either envelope or hvac (Window, Wall, Space Floor) or (System->Plant) # # Hierarchy) this is required to determine parent/child relationships in the building. # def doe_scope # scope = "none" # @envelopeLevel.each_index do |index| # @envelopeLevel[index].each do |name| # if (@commandName == name ) # scope = "envelope" # end # end # end # # @hvacLevel.each_index do |index| # @hvacLevel[index].each do |name| # if (@commandName == name ) # scope = "hvac" # end # end # end # return scope # end # # Determines the DOE scope depth (Window, Wall, Space Floor) or (System->Plant) Hierarchy) # def depth # level = 0 # scopelist=[] # if (doe_scope == "hvac") # scopelist = @hvacLevel # else # scopelist = @envelopeLevel # end # scopelist.each_index do |index| # scopelist[index].each do |name| # if (@commandName == name ) # level = index # end # end # end # return level # end # # #Outputs the command in DOE 2.2 format. # def output # return basic_output() # end # # #Outputs the command in DOE 2.2 format. # def basic_output() # temp_string = String.new() # # if (@utype != "") # temp_string = temp_string + "#{@utype} = " # end # temp_string = temp_string + @commandName # temp_string = temp_string + "\n" # @keywordPairs.each {|array| temp_string = temp_string + "\t#{array[0]} = #{array[1]}\n" } # temp_string = temp_string + "..\n" # # temp_string = temp_string + "$Parents\n" # @parents.each do |array| # temp_string = temp_string + "$\t#{array.utype} = #{array.commandName}\n" # end # temp_string = temp_string + "..\n" # # temp_string = temp_string + "$Children\n" # @children.each {|array| temp_string = temp_string + "$\t#{array.utype} = #{array.commandName}\n" } # temp_string = temp_string + "..\n" # # end # # # Creates the command informantion based on DOE 2.2 syntax. # def get_command_from_string(command_string) # #Split the command based on the equal '=' sign. # remove = "" # keyword="" # value="" # # if (command_string != "") # #Get command and u-value # if ( command_string.match(/(^\s*(\".*?\")\s*\=\s*(\S+)\s*)/) ) # @commandName=$3.strip # @utype = $2.strip # remove = Regexp.escape($1) # # else # # if no u-value, get just the command. # command_string.match(/(^\s*(\S*)\s)/ ) # remove = Regexp.escape($1) # @commandName=$2.strip # end # #Remove command from string. # # command_string.sub!(/#{remove}/,"") # command_string.strip! # # # #Loop throught the keyword values. # while ( command_string.length > 0 ) # #DOEMaterial, or SCHEDULES # if ( command_string.match(/(^\s*(MATERIAL|DAY-SCHEDULES|WEEK-SCHEDULES)\s*(\=?)\s*(.*)\s*)/)) # #puts "Bracket" # keyword = $2.strip # value = $4.strip # remove = Regexp.escape($1) # #Stars # elsif ( command_string.match(/(^\s*(\S*)\s*(\=?)\s*(\*.*?\*)\s*)/)) # #puts "Bracket" # keyword = $2.strip # value = $4.strip # remove = Regexp.escape($1) # # #Brackets # elsif ( command_string.match(/(^\s*(\S*)\s*(\=?)\s*(\(.*?\))\s*)/)) # #puts "Bracket" # keyword = $2.strip # value = $4.strip # remove = Regexp.escape($1) # #Quotes # elsif ( command_string.match(/(^\s*(\S*)\s*(\=?)\s*(".*?")\s*)/) ) # #puts "Quotes" # keyword = $2 # value = $4.strip # remove = Regexp.escape($1) # #single command # elsif command_string.match(/(^\s*(\S*)\s*(\=?)\s*(\S+)\s*)/) # #puts "Other" # keyword = $2 # value = $4.strip # remove = Regexp.escape($1) # end # #puts "DOE22::DOECommand: #{command_string}" # #puts "K = #{keyword} V = #{value}\n" # if (keyword != "") # set_keyword_value(keyword,value) # end # command_string.sub!(/#{remove}/,"") # end # #puts "Keyword" # #puts keywordPairs # end # end # # #Returns an array of the commands parents. # def get_parents # return @parents # end # # #Returns an array of the commands children. # def get_children # return children # end # # # Gets name. # def get_name() # return @utype # end # # # Check if keyword exists. # def check_keyword?(keyword) # @keywordPairs.each do |pair| # if pair[0] == keyword # return true # end # end # return false # end # # # Gets the parent of command...if any. # def get_parent(keyword) # # get_parents().each do |findcommand| # # if ( findcommand.commandName == keyword) # return findcommand # end # end # return nil # # end # # #Gets children of command, if any. # def get_children_of_command(keyword) # array = Array.new() # children.each do |findcommand| # if ( findcommand.commandName == keyword) # array.push(findcommand) # end # end # return array # end # # def name() # return utype # end # # private # def add_keyword_pair(keyword,pair) # array = [keyword,pair] # keywordPairs.push(array) # end # end # class DOEZone < BTAP::EQuest::DOECommand # attr_accessor :space # # a vector of spaces used when the declaration of space is "combined" # attr_accessor :space_uses # # a lighting object which stores the lighting characteristics of each zone # attr_accessor :lighting # #defines the thermal mass characteristics of the zone. # #could be a string object or a user defined object # attr_accessor :thermal_mass # # stores a constant floating value of the amount of air leakage, # #accoriding to rule #4.3.5.9. # attr_accessor :air_leakage # # this will be a vector consisting of heat transfer objects, # # which contains a pointer to the adjacent thermal block and a pointer # # to the wall in between them # attr_accessor :heat_transfers # def initialize # super() # end # # def output # # temp_string = basic_output() # if (@space == nil) # temp_string = temp_string + "$ No space found to match zone!\n" # else # temp_string = temp_string + "$Space\n" # temp_string = temp_string + "$\t#{@space.utype} = #{@space.commandName}\n" # end # return temp_string # end # # # This method finds all the exterior surfaces, ie. Exterior Wall and Roof # # Output => surfaces as an Array of commands # def get_exterior_surfaces() # surfaces = Array.new() # @space.get_children().each do |child| # # if child.commandName == "EXTERIOR-WALL" || # child.commandName == "ROOF" # surfaces.push(child) # end # end # return surfaces # end # # # This method returns all the children of the space # def get_children() # return @space.get_children() # end # # # # # This method returns the area of the space # def get_area() # @space.get_area() # end # # # # # def convert_to_openstudio(model,runner = nil) # if self.space.get_shape() == "NO-SHAPE" # BTAP::runner_register("Info", "Thermal Zone contains a NO-SHAPE space named. OS does not support no shape spaces. Thermal Zone will not be created.",runner) # else # os_zone = OpenStudio::Model::ThermalZone.new(model) # os_zone.setName(self.name) # #set space to thermal zone # OpenStudio::Model::getSpaceByName(model,self.space.name).get.setThermalZone(os_zone) # BTAP::runner_register("Info", "\tThermalZone: " + self.name + " created",runner) # end # end # end # # # class DOESurface < DOECommand # attr_accessor :construction # attr_accessor :polygon # # def initialize # super() # @polygon = nil # end # # def get_azimuth() # #puts OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 0.0, 0.0), OpenStudio::Vector3d.new(1.0, 0.0, 0.0) ) ) # if check_keyword?("LOCATION") # case get_keyword_value("LOCATION") # when /SPACE-\s*V\s*(.*)/ # index = $1.strip.to_i - 1 # point0 = self.get_parent("SPACE").polygon.point_list[index] # point1 = self.get_parent("SPACE").polygon.point_list[index + 1] ? get_parent("SPACE").polygon.point_list[index + 1] : get_parent("SPACE").polygon.point_list[0] # edge = point1-point0 # # sign = OpenStudio::Vector3d.new(1.0, 0.0, 0.0).dot(( edge )) > 0 ? 1 :-1 # angle = OpenStudio::radToDeg( sign * OpenStudio::getAngle(OpenStudio::Vector3d.new(1.0, 0.0, 0.0), ( point1 - point0 ) ) ) # # #since get angle only get acute angles we need to get sign and completment for reflex angle # angle = angle + 180 if edge.y < 0 # return angle # when "FRONT" # return OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 1.0, 0.0), ( get_parent("SPACE").polygon.point_list[1] - get_parent("SPACE").polygon.point_list[0] ) ) ) # when "RIGHT" # return OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 1.0, 0.0), ( get_parent("SPACE").polygon.point_list[2] - get_parent("SPACE").polygon.point_list[1] ) ) ) # when "BACK" # return OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 1.0, 0.0), ( get_parent("SPACE").polygon.point_list[3] - get_parent("SPACE").polygon.point_list[2] ) ) ) # when "LEFT" # return OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 1.0, 0.0), ( get_parent("SPACE").polygon.point_list[0] - get_parent("SPACE").polygon.point_list[3] ) ) ) # end # end # return self.check_keyword?("AZIMUTH")? self.get_keyword_value("AZIMUTH").to_f : 0.0 # end # # def get_tilt() # #puts OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 0.0, 0.0), OpenStudio::Vector3d.new(1.0, 0.0, 0.0) ) ) # if check_keyword?("LOCATION") # case get_keyword_value("LOCATION") # when "FRONT","BACK","LEFT","RIGHT",/SPACE-\s*V\s*(.*)/ # return 90.0 # when "TOP" # return 0.0 # when "BOTTOM" # return 180.0 # end # end # return self.check_keyword?("TILT")? self.get_keyword_value("TILT").to_f : 0.0 # end # # # # # def get_origin() # space_xref = self.check_keyword?("X")? self.get_keyword_value("X").to_f : 0.0 # space_yref = self.check_keyword?("Y")? self.get_keyword_value("Y").to_f : 0.0 # space_zref = self.check_keyword?("Z")? self.get_keyword_value("Z").to_f : 0.0 # return OpenStudio::Vector3d.new(space_xref,space_yref,space_zref) # end # # def get_sub_surface_origin() # height = "" # BTAP::runner_register("Info", "geting origin",runner) # origin = "" # if self.check_keyword?("X") and self.check_keyword?("Y") and self.check_keyword?("Z") # BTAP::runner_register("Info", "XYZ definition",runner) # space_xref = self.get_keyword_value("X").to_f # space_yref = self.get_keyword_value("Y").to_f # space_zref = self.get_keyword_value("Z").to_f # return OpenStudio::Vector3d.new(space_xref,space_yref,space_zref) # end # BTAP::runner_register("Info", get_name(),runner) # array = Array.new() # origin = "" # floor = get_parent("FLOOR") # space = get_parent("SPACE") # case space.get_keyword_value("ZONE-TYPE") # when "PLENUM" # height = floor.get_keyword_value("FLOOR-HEIGHT").to_f - floor.get_keyword_value("SPACE-HEIGHT").to_f # when "CONDITIONED","UNCONDITIONED" # height = space.check_keyword?("HEIGHT") ? space.get_keyword_value("HEIGHT").to_f : floor.get_keyword_value("SPACE-HEIGHT").to_f # # end # BTAP::runner_register("Info", "Space is #{space.get_shape}",runner) # case space.get_shape # when "BOX" # BTAP::runner_register("Info", "Box Space Detected....",runner) # #get height, width and depth of box. # height = space.check_keyword?("HEIGHT").to_f ? space.check_keyword?("HEIGHT") : height # width = space.get_keyword_value("WIDTH").to_f # depth = space.get_keyword_value("DEPTH").to_f # # case get_keyword_value("LOCATION") # when "TOP" # BTAP::runner_register("Info", "Top of Box....",runner) # #counter clockwise # origin = OpenStudio::Point3d.new(0.0,0.0,height) # # when "BOTTOM" # BTAP::runner_register("Info", "Bottom of Box....",runner) # #counter clockwise # origin = OpenStudio::Point3d.new( 0.0, 0.0, 0.0 ) # when "FRONT" # BTAP::runner_register("Info", "Front of Box....",runner) # #counter clockwise # origin = OpenStudio::Point3d.new( 0.0, 0.0, 0.0 ) # when "RIGHT" # BTAP::runner_register("Info", "Right of Box....",runner) # #counter clockwise # origin = OpenStudio::Point3d.new(width, 0.0, 0.0) # when "BACK" # BTAP::runner_register("Info", "Back of Box....",runner) # #counter clockwise # origin = OpenStudio::Point3d.new(width,depth,0.0) # when "LEFT" # BTAP::runner_register("Info", "Left of Box....",runner) # #counter clockwise # origin = OpenStudio::Point3d.new(0.0,depth,0.0) # # end # # when "POLYGON" # #puts "Polygon Space definition detected..." # if check_keyword?("LOCATION") # #puts "LOCATION surface definition detected..." # case get_keyword_value("LOCATION") # when "BOTTOM" # origin = OpenStudio::Vector3d.new(0.0,0.0, 0.0 ) # when "TOP" # #puts "TOP surface definition detected..." # #need to move floor polygon up to space height for top. Using Transformation.translation matrix for this. # # origin = OpenStudio::Vector3d.new(0.0,0.0, height ) #to-do!!!!!!!!!!! # when /SPACE-\s*V\s*(.*)/ # #puts "SPACE-V#{$1} surface definition detected..." # index = $1.strip.to_i - 1 # point0 = space.polygon.point_list[index] # #counter clockwise # origin = OpenStudio::Point3d.new( point0.x, point0.y, 0.0) # # end # else # #puts "CATCH-ALL for surface definition.." # #nasty. The height is NOT defined if the height is the same as the space height...so gotta get it from it's parent space. # space_height = space.check_keyword?("HEIGHT") ? space.get_keyword_value("HEIGHT").to_f : floor.get_keyword_value("SPACE-HEIGHT").to_f # height = self.check_keyword?("HEIGHT") ? self.get_keyword_value("HEIGHT").to_f : space_height # width = self.get_keyword_value("WIDTH").to_f # #origin # origin = OpenStudio::Point3d.new(width,0.0,0.0) # end # when "NO-SHAPE" # raise("Using SHAPE = NO-SHAPE deifnition for space is not supported by open Studio") # end # # origin = OpenStudio::Vector3d.new(origin.x,origin.y,origin.z) # #puts "Surface origin vector is #{origin}" # return origin # end # # # # def get_transformation_matrix # #Rotate points around z (azimuth) and x (Tilt) # translation = OpenStudio::createTranslation(self.get_origin) # e_a = OpenStudio::EulerAngles.new( OpenStudio::degToRad( self.get_tilt ), 0.0, OpenStudio::degToRad( 180.0 - self.get_azimuth ) ) # rotations = OpenStudio::Transformation::rotation(e_a) # return translation * rotations # end # # def get_3d_polygon() # array = Array.new() # origin = "" # floor = get_parent("FLOOR") # space = get_parent("SPACE") # case space.get_keyword_value("ZONE-TYPE") # when "PLENUM" # height = floor.get_keyword_value("FLOOR-HEIGHT").to_f - floor.get_keyword_value("SPACE-HEIGHT").to_f # when "CONDITIONED","UNCONDITIONED" # height = space.check_keyword?("HEIGHT") ? space.get_keyword_value("HEIGHT").to_f : floor.get_keyword_value("SPACE-HEIGHT").to_f # end # # #if the surface has been given a polygon. Then use it. # if check_keyword?("POLYGON") # # puts "Polygon Surface Detected...Doing a local transform.." # # # # puts "Point List" # # puts self.polygon.point_list # # puts "Origin" # # puts self.get_origin # # puts "azimuth" # # puts self.get_azimuth # # puts "tilt" # # puts self.get_tilt # # # # #all other methods below create points relative to the space. This method however, need to be transformed. # array = self.polygon.point_list # # # #if surfaces are defined by shape of space. # else # case space.get_shape # when "BOX" # BTAP::runner_register("Info", "Box Space Detected....",runner) # #get height, width and depth of box. # height = space.check_keyword?("HEIGHT").to_f ? space.check_keyword?("HEIGHT") : height # width = space.get_keyword_value("WIDTH").to_f # depth = space.get_keyword_value("DEPTH").to_f # # case get_keyword_value("LOCATION") # when "TOP" # #puts "Top of Box...." # #counter clockwise # origin = OpenStudio::Point3d.new(0.0,0.0,height) # p2 = OpenStudio::Point3d.new(width,0.0,height) # p3 = OpenStudio::Point3d.new(width,depth,height) # p4 = OpenStudio::Point3d.new(0.0,depth,height) # array = [origin,p2,p3,p4] # when "BOTTOM" # #puts "Bottom of Box...." # #counter clockwise # origin = OpenStudio::Point3d.new( 0.0, 0.0, 0.0 ) # p2 = OpenStudio::Point3d.new( 0.0, depth, 0.0) # p3 = OpenStudio::Point3d.new( width, depth, 0.0) # p4 = OpenStudio::Point3d.new( width,0.0 ,0.0 ) # array = [origin,p2,p3,p4] # when "FRONT" # #puts "Front of Box...." # #counter clockwise # origin = OpenStudio::Point3d.new( 0.0, 0.0, 0.0 ) # p2 = OpenStudio::Point3d.new( width,0.0 ,0.0 ) # p3 = OpenStudio::Point3d.new( width, 0.0, height) # p4 = OpenStudio::Point3d.new( 0.0, 0.0, height) # array = [origin,p2,p3,p4] # when "RIGHT" # #puts "Right of Box...." # #counter clockwise # origin = OpenStudio::Point3d.new(width, 0.0, 0.0) # p2 = OpenStudio::Point3d.new(width,depth, 0.0) # p3 = OpenStudio::Point3d.new(width,depth,height) # p4 = OpenStudio::Point3d.new(width,0.0,height) # array = [origin,p2,p3,p4] # when "BACK" # #puts "Back of Box...." # #counter clockwise # origin = OpenStudio::Point3d.new(width,depth,0.0) # p2 = OpenStudio::Point3d.new(0.0,depth,0.0) # p3 = OpenStudio::Point3d.new(0.0,depth,height) # p4 = OpenStudio::Point3d.new(width,depth,height) # array = [origin,p2,p3,p4] # when "LEFT" # #puts "Left of Box...." # #counter clockwise # origin = OpenStudio::Point3d.new(0.0,depth,0.0) # p2 = OpenStudio::Point3d.new( 0.0, 0.0, 0.0 ) # p3 = OpenStudio::Point3d.new(0.0, 0.0,height) # p4 = OpenStudio::Point3d.new(0.0,depth,height) # array = [origin,p2,p3,p4] # end # # when "POLYGON" # #puts "Polygon Space definition detected..." # if check_keyword?("LOCATION") # #puts "LOCATION surface definition detected..." # case get_keyword_value("LOCATION") # when "BOTTOM" # #puts "BOTTOM surface definition detected..." # #reverse array # array = space.polygon.point_list.dup # first = array.pop # array.insert(0,first).reverse! # when "TOP" # #puts "TOP surface definition detected..." # #need to move floor polygon up to space height for top. Using Transformation.translation matrix for this. # array = OpenStudio::createTranslation(OpenStudio::Vector3d.new(0.0,0.0, height )) * space.polygon.point_list # when /SPACE-\s*V\s*(.*)/ # #puts "SPACE-V#{$1} surface definition detected..." # index = $1.strip.to_i - 1 # point0 = space.polygon.point_list[index] # point1 = space.polygon.point_list[index + 1] ? space.polygon.point_list[index + 1] : space.polygon.point_list[0] # #counter clockwise # origin = OpenStudio::Point3d.new( point0.x, point0.y, 0.0) # p2 = OpenStudio::Point3d.new( point1.x, point1.y, 0.0) # p3 = OpenStudio::Point3d.new( point1.x, point1.y, height ) # p4 = OpenStudio::Point3d.new( point0.x, point0.y, height ) # array = [origin,p2,p3,p4] # end # else # #puts "CATCH-ALL for surface definition.." # #nasty. The height is NOT defined if the height is the same as the space height...so gotta get it from it's parent space. # space_height = space.check_keyword?("HEIGHT") ? space.get_keyword_value("HEIGHT").to_f : floor.get_keyword_value("SPACE-HEIGHT").to_f # height = self.check_keyword?("HEIGHT") ? self.get_keyword_value("HEIGHT").to_f : space_height # width = self.get_keyword_value("WIDTH").to_f # #counter clockwise # origin = OpenStudio::Point3d.new(width,0.0,0.0) # p2 = OpenStudio::Point3d.new( 0.0,0.0,0.0 ) # p3 = OpenStudio::Point3d.new(0.0,0.0,height) # p4 = OpenStudio::Point3d.new(width,0.0,height) # array = [p4, p3, p2, origin] # # # # end # when "NO-SHAPE" # raise("Using SHAPE = NO-SHAPE deifnition for space is not supported...yet") # end # end # # if self.check_keyword?("AZIMUTH") or self.check_keyword?("TILT") # # puts "Did a transform" # # return get_transformation_matrix * array # # else # # return array # # end # return array # end # # # def get_windows() # return self.get_children_of_command("WINDOW") # end # # def get_doors() # return self.get_children_of_command("DOOR") # end # # # # # This method finds all the commands within the building that are "Construction" # # and if the utype matches, it gets the construction # def determine_user_defined_construction() # constructions = @building.find_all_commands("CONSTRUCTION") # constructions.each do |construction| # if ( construction.utype == get_keyword_value("CONSTRUCTION") ) # @construction = construction # end # end # return @construction # end # # #This method will try to convert a DOE inp file to an openstudio file.. # def convert_to_openstudio(model,runner = nil) # #Get 3d polygon of surface and tranform the points based on space origin and the floor origin since they each may use their own co-ordinate base system. # total_transform = "" # if self.check_keyword?("AZIMUTH") or self.check_keyword?("TILT") # total_transform = get_parent("FLOOR").get_transformation_matrix() * get_parent("SPACE").get_transformation_matrix() * get_transformation_matrix() # else # total_transform = get_parent("FLOOR").get_transformation_matrix() * get_parent("SPACE").get_transformation_matrix() # end # surface_points = total_transform * self.get_3d_polygon() # #Add the surface to the new openstudio model. # # os_surface = OpenStudio::Model::Surface.new(surface_points, model) # #set the name of the surface. # os_surface.setName(self.name) # case self.commandName # #Set the surface boundary condition if it is a ground surface. # # when "UNDERGROUND-WALL" # BTAP::Geometry::Surfaces::set_surfaces_boundary_condition(model,os_surface, "Ground") # when "EXTERIOR-WALL","ROOF" # #this is needed since the surface constructor defaults to a Ground boundary and Floor Surface type # #when a horizontal surface is initialized. # if os_surface.outsideBoundaryCondition == "Ground" and os_surface.surfaceType == "Floor" # os_surface.setSurfaceType("RoofCeiling") # end # BTAP::Geometry::Surfaces::set_surfaces_boundary_condition(model,os_surface, "Outdoors") # when "INTERIOR-WALL" # BTAP::Geometry::Surfaces::set_surfaces_boundary_condition(model,os_surface, "Surface") # end # # #Add to parent space that was already created. # os_surface.setSpace(OpenStudio::Model::getSpaceByName( model,get_parent("SPACE").name).get ) # #output to console for debugging. # BTAP::runner_register("Info", "\tSurface: " + self.name + " created",runner) # #check if we need to create a mirror surface in another space. # if self.check_keyword?("NEXT-TO") # #reverse the points. # new_array = surface_points.dup # first = new_array.pop # new_array.insert(0,first).reverse! # #...then add the reverse surface to the model and assign the name with a mirror suffix. # os_surface_mirror = OpenStudio::Model::Surface.new(new_array, model) # os_surface_mirror.setName(self.name + "-mirror" ) # #Assign the mirror surface to the parent space that is NEXT-TO # os_surface_mirror.setSpace(OpenStudio::Model::getSpaceByName(model,get_keyword_value("NEXT-TO")).get) # #output to console for debugging. # BTAP::runner_register("Info", "\tSurface: " + self.name + "-mirror" + " created",runner) # end #if statement # # #Some switches for debugging. # convert_sub_surfaces = true # convert_sub_surfaces_as_surfaces = false # # # # if convert_sub_surfaces # #convert subsurfaces # self.get_children().each do |child| # #Get height and width of subsurface # height = child.get_keyword_value("HEIGHT").to_f # width = child.get_keyword_value("WIDTH").to_f # # # #Sum the origin of the surface and the translation of the window # x = os_surface.vertices.first().x + ( child.check_keyword?("X")? child.get_keyword_value("X").to_f : 0.0 ) # y = os_surface.vertices.first().y + ( child.check_keyword?("Y")? child.get_keyword_value("Y").to_f : 0.0 ) # z = os_surface.vertices.first().z # # #counter clockwise # origin = OpenStudio::Point3d.new( x, y , z ) # p2 = OpenStudio::Point3d.new(x + width , y, z ) # p3 = OpenStudio::Point3d.new(x + width , y + height , z ) # p4 = OpenStudio::Point3d.new(x, y + height, z ) # polygon = [origin,p2,p3,p4] # # #get floot and space rotations # space_azi = 360.0 - get_parent("SPACE").get_azimuth() # floor_azi = 360.0 - get_parent("FLOOR").get_azimuth() # # # tilt_trans = OpenStudio::Transformation::rotation(os_surface.vertices.first(), OpenStudio::Vector3d.new(1.0,0.0,0.0), OpenStudio::degToRad( self.get_tilt )) # azi_trans = OpenStudio::Transformation::rotation(os_surface.vertices.first(), OpenStudio::Vector3d.new(0.0,0.0,1.0), OpenStudio::degToRad( 360.0 - self.get_azimuth + space_azi + floor_azi )) # surface_points = azi_trans * tilt_trans * polygon # if convert_sub_surfaces_as_surfaces # #Debug subsurface # os_sub_surface = OpenStudio::Model::Surface.new(surface_points, model) # #set the name of the surface. # os_sub_surface.setName(child.name) # #Add to parent space that was already created. # os_sub_surface.setSpace(OpenStudio::Model::getSpaceByName( model,self.get_parent("SPACE").name).get ) # else # #Add the subsurface to the new openstudio model. # os_sub_surface = OpenStudio::Model::SubSurface.new(surface_points, model) # #set the name of the surface. # os_sub_surface.setName(child.name) # #Add to parent space that was already created. # os_sub_surface.setSurface(os_surface) # #output to console for debugging. # BTAP::runner_register("Info", "\tSubSurface: " + child.name + " created",runner) # case child.commandName # when "WINDOW" # #By default it is a window. # when "DOOR" # os_sub_surface.setSubSurfaceType( "Door" ) # end #end case. # # # Add overhang for subsurface if required. Note this only supports overhangs of width the same as the window. # if child.check_keyword?("OVERHANG-D") == true # offset = 0.0 # offset = child.get_keyword_value("OVERHANG-O").to_f if child.check_keyword?("OVERHANG-O") # depth = 0.0 # depth = child.get_keyword_value("OVERHANG-D").to_f # os_sub_surface.addOverhang( depth , offset ) # end # # end # end # end # end # # end # # #This class allows to manipulate a subsurface (window/door) in inherits from surface. # class DOESubSurface < DOESurface # # def initialize # #run the parent class initialization. # super() # end # # # This method returns the area of the window # def get_area() # unless check_keyword?("HEIGHT") and check_keyword?("WIDTH") # raise "Error: In the command #{@utype}:#{@command_name} the area could not be evaluated. Either the HEIGHT or WIDTH is invalid.\n #{output}" # end # return get_keyword_value("WIDTH").to_f * get_keyword_value("HEIGHT").to_f # end # # #Return the widow polygon with an origin of zero # def get_3d_polygon() # height = get_keyword_value("HEIGHT").to_f # width = get_keyword_value("WIDTH").to_f # x = self.check_keyword?("X")? self.get_keyword_value("X").to_f : 0.0 # y = self.check_keyword?("Y")? self.get_keyword_value("Y").to_f : 0.0 # #counter clockwise # origin = OpenStudio::Point3d.new( x, y , 0.0 ) # p2 = OpenStudio::Point3d.new(x + width , y,0.0 ) # p3 = OpenStudio::Point3d.new(x + width , y + height , 0.0 ) # p4 = OpenStudio::Point3d.new(x, y + height,0.0 ) # return [origin,p2,p3,p4] # end # # #Returns the origin relative to the parent surface. # def get_origin() # origin = get_parent_surface().get_sub_surface_origin() # return origin # end # # #Gets azimuth, based on parent surface. # def get_azimuth() # get_parent_surface().get_azimuth() # end # # #gets tilt based on parent surface. # def get_tilt() # get_parent_surface().get_tilt() # end # # #return the parent surface of the subsurface. # def get_parent_surface() # get_parents().each do |findcommand| # [ # "EXTERIOR-WALL", # "INTERIOR-WALL", # "UNDERGROUND-WALL", # "ROOF" # ].each do |type| # # if ( findcommand.commandName == type) # return findcommand # end # end # end # raise("#no parent surface defined!") # end # # #returns the translation matrix reletive to its parent ( the surface ) # def get_transformation_matrix # return self.get_rotation_matrix() * self.get_translation_matrix() # end # # def get_rotation_matrix # #Rotate points around z (azimuth) and x (Tilt) # e_a = OpenStudio::EulerAngles.new( OpenStudio::degToRad( self.get_tilt ), 0.0, OpenStudio::degToRad( 0.0 ) ) # rotations = OpenStudio::Transformation::rotation(e_a) # return rotations # end # # def get_translation_matrix # #Rotate points around z (azimuth) and x (Tilt) # translation = OpenStudio::createTranslation(self.get_origin) # return translation # end # # # # # # # this will translate the subsurface to the openstudio model. # def convert_to_openstudio(model) # end # end # # #an attempt to organize the BDLlibs...don't think it works well at all. # class DOEBDLlib # # attr_accessor :db, :materials # # include Singleton # # # # # # stores the name of the individual materials # # attr_accessor :commandList # # stores the name of the individual layers # # # def initialize # @commandList = Array.new() # @db = Sequel.sqlite # @db.create_table :materials do # Create a new table # primary_key :id, :integer, :auto_increment => true # column :command_name, :text # column :name, :text # column :type, :text # column :thickness, :float # column :conductivity, :float # column :resistance, :float # column :density, :float # column :spec_heat, :float # end # @materials = @db[:materials] # Create a dataset # # @db.create_table :layers do # Create a new table # primary_key :id, :integer, :auto_increment => true # column :command_name, :text # column :name, :text # column :material, :text # column :inside_film_res, :float # end # @layers = @db[:layers] # Create a dataset # # # store_material() # end # # # # def find_material(utype) # posts = @materials.filter(:name => utype) # record = posts.first() # #Create the new command object. # command = DOE2::DOECommand.new() # #Insert the collected information into the object. # command.commandName = "MATERIAL" # command.utype = record[:name] # command.set_keyword_value("TYPE", record[:type]) # command.set_keyword_value("THICKNESS", record[:thickness]) # command.set_keyword_value("CONDUCTIVITY", record[:conductivity]) # command.set_keyword_value("DENSITY", record[:density]) # command.set_keyword_value("SPECIFIC HEAT", record[:spec_heat]) # # return command # end # # # def find_layer(utype) # posts = @layers.filter(:name => utype) # record = posts.first() # #Create the new command object. # command = DOE2::DOECommand.new() # #Insert the collected information into the object. # command.commandName = "LAYERS" # command.utype = record[:name] # command.set_keyword_value("MATERIAL", record[:material]) # command.set_keyword_value("THICKNESS", record[:thickness]) # command.set_keyword_value("CONDUCTIVITY", record[:conductivity]) # command.set_keyword_value("DENSITY", record[:density]) # command.set_keyword_value("SPECIFIC HEAT", record[:spec_heat]) # # return command # end # # # # # # # stores the material information using keywordPairs into the command structure # # accessed using the find_command method # private # def store_material # # begin # f = File.open("../Resources/DOE2_2/bdllib.dat") # rescue # f = File.open("Resources/DOE2_2/bdllib.dat") # end # # lines = f.readlines # # Iterating through the file. # lines.each_index do |i| # command_string = "" # # If we find a material. # if lines[i].match(/\$LIBRARY-ENTRY\s(.{32})MAT .*/) # #Get the name strips the white space. # name = ("\""+$1.strip + "\"") # # #Is this the last line? # command_string = get_data(command_string, i, lines) # #Extract data for material type PROPERTIES. # if (match = command_string.match(/^\s*TYPE\s*=\s*(\S*)\s*TH\s*=\s*(\S*)\s*COND\s*=\s*(\S*)\s*DENS\s*=\s*(\S*)\s*S-H\s*=\s*(\S*)\s*$/) ) # #Create the new command object. # command = DOE2::DOECommand.new() # #Insert the collected information into the object. # command.commandName = "MATERIAL" # command.utype = name # command.set_keyword_value("TYPE", $1.strip) # command.set_keyword_value("THICKNESS", $2.strip.to_f.to_s) # command.set_keyword_value("CONDUCTIVITY", $3.strip.to_f.to_s) # command.set_keyword_value("DENSITY", $4.strip.to_f.to_s) # command.set_keyword_value("SPECIFIC HEAT", $5.strip.to_f.to_s) # #Push the object into the array for storage. # @commandList.push(command) # @materials << {:name => name, # :command_name => 'MATERIAL', # :type => $1.strip, # :thickness => $2.strip.to_f.to_s, # :conductivity => $3.strip.to_f.to_s, # :density => $4.strip.to_f.to_s, # :spec_heat => $5.strip.to_f.to_s} # # # # #Extract data for material type RESISTANCE. # elsif (match = command_string.match(/^\s*TYPE\s*=\s*(\S*)\s*RES\s*=\s*(\S*)\s*$/) ) # command = DOE2::DOECommand.new() # command.commandName = "MATERIAL" # command.utype = name # command.set_keyword_value("TYPE", $1.strip) # command.set_keyword_value("RESISTANCE", $2.strip.to_f.to_s) # #Push the object into the array for storage. # @materials << {:name => name, # :command_name => 'MATERIAL', # :type => $1.strip, # :resistance => $2.strip.to_f.to_s} # # @commandList.push(command) # else # raise("data not extracted") # end # end # # if lines[i].match(/\$LIBRARY-ENTRY\s(.{32})LA .*/) # #Get the name # name = ("\""+$1.strip + "\"") # #Is this the last line? # command_string = get_data(command_string, i, lines) # #Extract data into the command. # if (match = command_string.match(/^\s*MAT\s*=\s*(.*?)\s*I-F-R\s*=\s*(\S*)\s*$/) ) # command = DOE2::DOECommand.new() # command.commandName = "LAYERS" # command.utype = name # command.set_keyword_value("MATERIAL",$1) # #Push the object into the array for storage. # @layers << {:name => name, # :command_name => 'LAYER', # :material => $1.strip, # :inside_film_res => $2.strip.to_f.to_s} # @commandList.push(command) # else # raise("data not extracted") # end # end # end # end # # private # # This method will get all the # def get_data(command_string, i, lines) # #Do this while this is NOT the last line of data. # while (! lines[i].match(/^(.*?)\.\.\s*(.{6})?\s*?(\d*)?/) ) # #Grab all the data in between. # if ( lines[i].match(/^\$.*$/) ) # elsif ( myarray = lines[i].match(/^(.*?)\s*(.{6})?\s*?(\d*)?\s*$/) ) # command_string = command_string + $1.strip # end # #Increment counter. # i = i + 1 # end # #Get the last line # lines[i].match(/^(.*?)\.\.\s*(.{6})?\s*?(\d*)?/) # command_string = command_string + $1.strip # if command_string == "" # raise("error") # end # i = i + 1 # command_string # end # end # # #class that # class DOEExteriorWall < DOESurface # # def initialize # #call the parent class. # super() # end # # # This method finds the area of the exterior wall # def get_area() # OpenStudio::getArea(self.get_3d_polygon()) # end # # #This method finds the floor parent # def get_floor() # get_parent("FLOOR") # end # # #This method finds the space parent command # def get_space() # get_parent("SPACE") # end # # #This method gets the construction command # def get_construction_name() # get_keyword_value("CONSTRUCTION") # end # # #This method returns the window area # def get_window_area() # get_children_area("WINDOW") # end # # #This method returns the door area # def get_door_area() # get_children_area("DOOR") # end # # # This method returns the difference between the wall area and the window # # and door # def get_opaque_area() # get_area.to_f - get_window_area().to_f - get_door_area().to_f # end # # # This method returns the fraction of the wall dominated by the window # def get_fwr() # get_window_area().to_f / get_area.to_f # end # # # This method returns the area of the children classes based on the given # # commandname. # # Input => A command_name as a String # # Output => Total area as a float # def get_children_area(scommand_name) # area = 0.0 # @children.each do |child| # # if child.commandName == scommand_name # area = child.get_area() + area # end # end # return area # end # # # This method checks if the construction only has a defined U-value # def just_u_value?() # @construction.check_keyword?("U-VALUE") # end # # # end # # # # # # # #The interface for the roof command.. same as parent. # class DOERoof < DOECommand # def initialize # super() # end # # # This method finds the area of the roof # def get_area # # # Finds the floor and space parents and assigns them to @floor and @space # # variables to be used later # parent = get_parents # parent.each do |findcommand| # if ( findcommand.commandName == "FLOOR" ) # @floor = findcommand # end # if ( findcommand.commandName == "SPACE") # @space = findcommand # end # end # # # Get the keyword value for location # begin # location = get_keyword_value("LOCATION") # rescue # end # # # Get the keyword value for polygon # begin # polygon_id = get_keyword_value("POLYGON") # rescue # end # # # if the polygon_id keyword value was nil and the location value was nil, then # # the height and width are directly defined within the "roof" command # # # if ( location == "BOTTOM" || location == "TOP") && (@space.get_shape != "BOX") # return @space.polygon.get_area # # elsif ( location == nil && polygon_id == nil ) # height = get_keyword_value("HEIGHT") # width = get_keyword_value("WIDTH") # height = height.to_f # width = width.to_f # return height * width # elsif ( location == nil && polygon_id != nil) # return @space.polygon.get_area # # # # if the location was defined as "SPACE...", it is immediately followed by a # # vertex, upon which lies the width of the roof # elsif location.match(/SPACE.*/) # location = location.sub( /^(.{6})/, "") # width = @space.polygon.get_length(location) # height = @floor.get_space_height # return width * height # # if the shape was a box, the width and height would be taken from the # # "SPACE" object # elsif ( @space.get_shape == "BOX" ) # width = @space.get_width # height = @space.get_height # return width * height # else # raise "The area could not be evaluated" # end # end # # #returns tilt of roof surface. # def get_tilt() # if check_keyword?("TILT") then return get_keyword_value("TILT").to_f # else # if check_keyword?("LOCATION") # location = get_keyword_value("LOCATION") # case location # when "TOP" # return 0.0 # when "BOTTOM" # return 180.0 # when "LEFT", "RIGHT", "BACK", "FRONT" # return 90.0 # end # end # # If it is a polygon or not defined, set to DOE default = 0.0 # return 0 # end # end # # # This method returns the Azimuth value as a FLOAT if it exists # # It first checks if the azimuth keyword value is present within the roof # # command itself. If it does not find this, then it checks for the location # # keyword and assigns the correct azimuth depending on the azimuth of the parent # # space. However, if the shape of the parent space is defined as a polygon, then it # # searches for the location of the roof and uses the polygon's get-azimuth for the vertex # # to return the azimuth of the roof # # #NOTE: The FRONT is defined as 0, going clockwise, ie. RIGHT = 90 degrees # # #OUTPUT: Azimuth between the parent SPACE and the ROOF # def get_azimuth() # space = get_parent("SPACE") # if check_keyword?("AZIMUTH") then return get_keyword_value("AZIMUTH").to_f # else # if check_keyword?("LOCATION") # location = get_keyword_value("LOCATION") # # case location # when "TOP" # raise "Exception: Azimuth does not exist" # when "BOTTOM" # raise "Exception: Azimuth does not exist" # when "FRONT" # return 0.0 + space.get_azimuth # when "RIGHT" # return 90.0 + space.get_azimuth # when "BACK" # return 180.0 + space.get_azimuth # when "LEFT" # return 270.0 + space.get_azimuth # end # end # if space.get_keyword_value("SHAPE") == "POLYGON" # space_vertex = get_keyword_value("LOCATION") # space_vertex.match(/SPACE-(.*)/) # vertex = $1.strip # return space.polygon.get_azimuth(vertex) # end # # end # end # # # This method returns the Azimuth value as a FLOAT if it exists # # It first checks if the azimuth keyword value is present within the roof # # command itself. If it does not find this, then it checks for the location # # keyword and assigns the correct azimuth depending on the azimuth of the parent # # space. However, if the shape of the parent space is defined as a polygon, then it # # searches for the location of the roof and uses the polygon's get-azimuth for the vertex # # and adding it on to the overall azimuth to get the Absolute Azimuth from True North # # #NOTE: The FRONT is defined as 0, going clockwise, ie. RIGHT = 90 degrees # # #OUTPUT: Azimuth between ROOF and TRUE NORTH # def get_absolute_azimuth # space = get_parent("SPACE") # if check_keyword?("AZIMUTH") # azimuth = get_keyword_value("AZIMUTH").to_f # space_azimuth = space.get_absolute_azimuth # return azimuth + space_azimuth # else # if check_keyword?("LOCATION") # location = get_keyword_value("LOCATION") # case location # when "TOP" # raise "Exception: Azimuth does not exist" # when "BOTTOM" # raise "Exception: Azimuth does not exist" # when "FRONT" # return 0.0 + space.get_absolute_azimuth # when "RIGHT" # return 90.0 + space.get_absolute_azimuth # when "BACK" # return 180.0 + space.get_absolute_azimuth # when "LEFT" # return 270.0 + space.get_absolute_azimuth # end # end # if space.get_keyword_value("SHAPE") == "POLYGON" # space_vertex = get_keyword_value("LOCATION") # space_vertex.match(/SPACE-(.*)/) # vertex = $1.strip # return space.polygon.get_azimuth(vertex) + space.get_absolute_azimuth # end # end # end # end # #Interface for the DOESpace Command. # class DOESpace < DOECommand # attr_accessor :polygon # attr_accessor :zone # def initialize # # super() # end # # #this outputs the command to a string. # def output # temp_string = basic_output() # if @polygon != nil # temp_string = temp_string + "$Polygon\n" # temp_string = temp_string + "$\t#{@polygon.utype} = #{@polygon.commandName}\n" # end # if @zone != nil # temp_string = temp_string + "$Zone\n" # temp_string = temp_string + "$\t#{@zone.utype} = #{@zone.commandName}\n" # end # return temp_string # end # # # This method finds the area of the space # def get_area # # # get the keyword value of shape # shape = get_keyword_value("SHAPE") # # # if the shape value is nil, or it is defined as "NO-SHAPE", the get_area value # # would be defined, and would represent the get_area of the space # if ( shape == nil || shape == "NO-SHAPE") # area = get_keyword_value("AREA") # area = area.to_f # return area # # # if the shape value is "BOX", the height and width key values are given, # # and the get_area would be defined as their product # elsif ( shape == "BOX" ) # height = get_keyword_value("HEIGHT") # width = get_keyword_value("WIDTH") # height = height.to_f # width = width.to_f # return height * width # # # if the shape value is defined as a polygon , the get_area of the polygon would # # represent the get_area of the space # elsif ( shape == "POLYGON") # return @polygon.get_area # else # raise "Error: The area could not be evaluated. Please check inputs\n " # # end # end # # # This method finds the volume of the space # def get_volume # # # get the keyword value of "SHAPE" # shape = get_keyword_value("SHAPE") # # # if the shape value returns nil, or is defined as "NO-SHAPE", the volume is # # given directly # if ( shape == nil || shape == "NO-SHAPE") # volume = get_keyword_value("VOLUME") # volume = volume.to_f # return volume # # # if the shape is defined as a "BOX", the values for height, width, and # # depth are given, from which you can get the volume # elsif ( shape == "BOX" ) # height = get_keyword_value("HEIGHT") # width = get_keyword_value("WIDTH") # depth = get_keyword_value("DEPTH") # height = height.to_f # width = width.to_f # depth = depth.to_f # return height * width * depth # # # if the shape is defined as a "POLYGON", the get_area is defined as the area # # of the polygon, and the height is given by the value of "HEIGHT" # elsif ( shape == "POLYGON") # height = getKeywordvalue("HEIGHT") # temp = get_keyword_value("POLYGON") # height = height.to_f # @polygon.utype = temp # return @polygon.get_area * height # else # raise "Error: The volume could not be evaluated. Please check inputs\n " # # end # # end # # def get_height() # if check_keyword?("HEIGHT") then return get_keyword_value("HEIGHT").to_f end # return get_floor.get_keyword_value("SPACE-HEIGHT").to_f # end # # def get_width # width = get_keyword_value("WIDTH") # width = width.to_f # return width # end # # def get_depth # depth = get_keyword_value("DEPTH") # depth = depth.to_f # return depth # end # # def get_shape # return "NO-SHAPE" unless check_keyword?("SHAPE") # return get_keyword_value("SHAPE") # end # # def get_floor # get_parent("FLOOR") # end # # # def get_origin() # space_origin = nil # if check_keyword?("LOCATION") and ( not self.check_keyword?("X") or not self.check_keyword?("Y") or not self.check_keyword?("Z") ) # zero = OpenStudio::Point3d.new( 0.0, 0.0, 0.0 ) # case get_keyword_value("LOCATION") # when /FLOOR-\s*V\s*(.*)/ # index = $1.strip.to_i - 1 # surf_vector = get_parent("FLOOR").polygon.point_list[index] - zero # when "FRONT" # surf_vector = get_parent("FLOOR").polygon.point_list[0] - zero # when "RIGHT" # surf_vector = get_parent("FLOOR").polygon.point_list[1] - zero # when "BACK" # surf_vector = get_parent("FLOOR").polygon.point_list[2] - zero # when "LEFT" # surf_vector = get_parent("FLOOR").polygon.point_list[3] - zero # end # space_xref = self.check_keyword?("X")? self.get_keyword_value("X").to_f : 0.0 # space_yref = self.check_keyword?("Y")? self.get_keyword_value("Y").to_f : 0.0 # space_zref = self.check_keyword?("Z")? self.get_keyword_value("Z").to_f : 0.0 # space_origin = OpenStudio::Vector3d.new(space_xref,space_yref,space_zref) # space_origin = surf_vector + space_origin # else # space_xref = self.check_keyword?("X")? self.get_keyword_value("X").to_f : 0.0 # space_yref = self.check_keyword?("Y")? self.get_keyword_value("Y").to_f : 0.0 # space_zref = self.check_keyword?("Z")? self.get_keyword_value("Z").to_f : 0.0 # space_origin = OpenStudio::Vector3d.new(space_xref,space_yref,space_zref) # end # return space_origin # end # # def get_azimuth() # angle = 0.0 # #puts OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 0.0, 0.0), OpenStudio::Vector3d.new(1.0, 0.0, 0.0) ) ) # if check_keyword?("LOCATION") and not check_keyword?("AZIMUTH") # case get_keyword_value("LOCATION") # when /FLOOR-\s*V\s*(.*)/ # index = $1.strip.to_i - 1 # point0 = self.get_parent("FLOOR").polygon.point_list[index] # point1 = self.get_parent("FLOOR").polygon.point_list[index + 1] ? get_parent("FLOOR").polygon.point_list[index + 1] : get_parent("FLOOR").polygon.point_list[0] # edge = point1-point0 # # # sign = 1.0# OpenStudio::Vector3d.new(1.0, 0.0, 0.0).dot(( edge )) > 0 ? 1 :-1 # angle = OpenStudio::radToDeg( sign * OpenStudio::getAngle(OpenStudio::Vector3d.new(1.0, 0.0, 0.0), ( point1 - point0 ) ) ) # # #since get angle only get acute angles we need to get sign and completment for reflex angle # if edge.y > 0.0 # angle = -1.0 * angle # end # # when "FRONT" # angle = OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 1.0, 0.0), ( get_parent("FLOOR").polygon.point_list[1] - get_parent("FLOOR").polygon.point_list[0] ) ) ) # when "RIGHT" # angle = OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 1.0, 0.0), ( get_parent("FLOOR").polygon.point_list[2] - get_parent("FLOOR").polygon.point_list[1] ) ) ) # when "BACK" # angle = OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 1.0, 0.0), ( get_parent("FLOOR").polygon.point_list[3] - get_parent("FLOOR").polygon.point_list[2] ) ) ) # when "LEFT" # angle = OpenStudio::radToDeg( OpenStudio::getAngle(OpenStudio::Vector3d.new(0.0, 1.0, 0.0), ( get_parent("FLOOR").polygon.point_list[0] - get_parent("FLOOR").polygon.point_list[3] ) ) ) # end # else # angle = self.check_keyword?("AZIMUTH")? self.get_keyword_value("AZIMUTH").to_f : 0.0 # end # return angle # end # # # def get_transformation_matrix() # #This will transform the space vertices to normal space co-ordinates using Sketchup/OS convention # return OpenStudio::createTranslation(self.get_origin) * OpenStudio::Transformation::rotation(OpenStudio::Vector3d.new(0.0, 0.0, 1.0), OpenStudio::degToRad(360.0 - self.get_azimuth())) # end # # def get_rotation_matrix() # return OpenStudio::Transformation::rotation(OpenStudio::Vector3d.new(0.0, 0.0, 1.0), OpenStudio::degToRad(360.0 - self.get_azimuth())) # end # # def convert_to_openstudio(model,runner = nil) # if self.get_keyword_value("SHAPE") == "NO-SHAPE" # BTAP::runner_register("Info", "OpenStudio does not support NO-SHAPE SPACE definitions currently. Not importing the space #{self.name}.",runner) # else # os_space = OpenStudio::Model::Space.new(model) # os_space.setName(self.name) # #set floor # os_space.setBuildingStory(OpenStudio::Model::getBuildingStoryByName(model,self.get_parent("FLOOR").name).get) # BTAP::runner_register("Info", "\tSpace: " + self.name + " created",runner) # #puts "\t\t Azimuth:#{self.get_azimuth}" # #puts "\t\t Azimuth:#{self.get_origin}" # end # end # # end # class DOEFloor < DOESurface # attr_accessor :polygon # # a string object which defines the type of roof (e.g. attic) # attr_accessor :type # # The absorptance of the exterior surface of the floor # # (see rule #4.3.5.3.(6) # attr_accessor :absorptance # # thermal insulation of floors # attr_accessor :thermal_insulation # # def initialize # super() # end # # #This method returns the floor area # def get_area # # # get the keyword for the shape of the floor # case get_keyword_value("SHAPE") # # # if the keyword value is "BOX", the width and depth values are defined # when "BOX" # return get_keyword_value("WIDTH").to_f * get_keyword_value("DEPTH").to_f # # # if the keyword value is "POLYGON", the get_area is defined as the area of the # # given polygon # when "POLYGON" # return @polygon.get_area # # # if the keyword value of the floor is "No-SHAPE", the get_area is given as the # # get_area keyword value # when "NO-SHAPE" # return get_keyword_value("AREA").to_f # else # raise "Error: The area could not be evaluated. Please check inputs\n " # end # end # # # This method returns the volume of the floor space # def get_volume # return get_floor_height.to_f * get_area.to_f # end # # # gets the height of the floor # def get_height # return get_keyword_value("FLOOR-HEIGHT").to_f # end # # # gets the space height # def get_space_height # return get_keyword_value("SPACE-HEIGHT").to_f # end # # def get_origin() # space_xref = self.check_keyword?("X")? self.get_keyword_value("X").to_f : 0.0 # space_yref = self.check_keyword?("Y")? self.get_keyword_value("Y").to_f : 0.0 # space_zref = self.check_keyword?("Z")? self.get_keyword_value("Z").to_f : 0.0 # return OpenStudio::Vector3d.new(space_xref,space_yref,space_zref) # end # # def get_azimuth() # return self.check_keyword?("AZIMUTH")? self.get_keyword_value("AZIMUTH").to_f : 0.0 # end # # def get_transformation_matrix() # return OpenStudio::createTranslation(self.get_origin) * OpenStudio::Transformation::rotation(OpenStudio::Vector3d.new(0.0, 0.0, 1.0), OpenStudio::degToRad(360.0 - self.get_azimuth())) # end # # def get_rotation_matrix() # return OpenStudio::Transformation::rotation(OpenStudio::Vector3d.new(0.0, 0.0, 1.0), OpenStudio::degToRad(360.0 - self.get_azimuth())) # end # # def convert_to_openstudio(model,runner = nil) # floor = OpenStudio::Model::BuildingStory.new(model) # floor.setName(self.name) # BTAP::runner_register("Info", "\tBuildingStory: " + self.name + " created",runner) # end # # end # #This class makes it easier to deal with DOE Polygons. # class DOEPolygon < DOECommand # # attr_accessor :point_list # # #The constructor. # def initialize # super() # @point_list = Array.new() # #Convert Keywork Pairs to points. # # end # # def create_point_list() # # #Convert Keywork Pairs to points. # @point_list.clear # @keywordPairs.each do |array| # # array[1].match(/\(\s*(\-?\d*\.?\d*)\s*\,\s*(\-?\d*\.?\d*)\s*\)/) # #puts array[1] # # point = OpenStudio::Point3d.new($1.to_f,$2.to_f,0.0) # @point_list.push(point) # end # # @point_list.each do |p| # # puts p.x.to_s + " " + p.y.to_s + " " + p.z.to_s + " " # # end # end # # # This method returns the area of the polygon. # def get_area # openstudio::getArea(@points_list) # end # # # # This method must determine the length of the given point to the next point # # in the polygon list. If the point is the last point, then it will be the # # distance from the last point to the first. # # point_name is the string named keyword in the keyword pair list. # # Example: # # "DOEPolygon 2" = POLYGON # # V1 = ( 0, 0 ) # # V2 = ( 0, 1 ) # # V3 = ( 2, 1 ) # # V4 = ( 2 ,0 ) # # get_length(3) should return "2" # # get_length(2) should return "1" # # def get_length(point_index) # if @points_list.size < pointindex + 2 # return OpenStudio::getDistance(@point_list[0],@point_list.last) # else # return OpenStudio::getDistance(@point_list[point_index],@point_list[point_index + 1] ) # end # end # # # def get_azimuth(point_index) # if @points_list.size < pointindex + 2 # return OpenStudio::radToDeg(OpenStudio::getAngle(@point_list.last - @point_list[0] , openstudio::Vector3d( 1.0, 0.0, 0.0))) # else # return OpenStudio::radToDeg(OpenStudio::getAngle(@point_list[point_index + 1] - @point_list[point_index] , openstudio::Vector3d( 1.0, 0.0, 0.0))) # end # end # # end # class DOELayer < DOECommand # # type of material (see rule #4.3.5.2.(3)) # attr_accessor :material # # the thickness of the material (see rule #4.3.5.2.(3)) # attr_accessor :thickness # def initialize # super() # end # end # class DOEMaterial < DOECommand # # characteristics of the materials # attr_accessor :density # attr_accessor :specific_heat # attr_accessor :thermal_conductivity # def initialize # super() # end # end # class DOEConstruction < DOECommand # # def initialize # super() # end # # def get_materials() # bdllib = DOE2::DOEBDLlib.instance # materials = Array.new # # case self.get_keyword_value("TYPE") # when "LAYERS" # # finds the command associated with the layers keyword # layers_command = building.find_command_with_utype( self.get_keyword_value("LAYERS") ) # # #if Layres command cannot be found in the inp file... find it in the bdl database. # layers_command = bdllib.find_layer(self.get_keyword_value("LAYERS")) unless layers_command.length == 1 # # # if there ends up to be more than one command with the layers keyword # # raise an exception # raise "Layers was defined more than once " + self.get_keyword_value("LAYERS").to_s if layers_command.length > 1 # # # get all the materials, separate it by the quotation marks and push it # # onto the materials array # layers_command[0].get_keyword_value("MATERIAL").scan(/(\".*?\")/).each do |material| # material_command = "" # # #Try to find material in doe model. # material_command_array = building.find_command_with_utype(material.to_s.strip) # # # if there ends up to be more than one, raise an exception # raise "Material was defined more than once #{material}" if material_command_array.length > 1 # # # if the material cannot be found within the model, find it within the doe2 database # material_command = bdllib.find_material(material) if material_command_array.length < 1 # # #If material was found then set it. # material_command = material_command_array[0] if material_command_array.length == 1 # # materials.push(material_command) # end # return materials # when "U-VALUE" # return nil # end # end # # # This method finds the u-value of the given construction # # Output => total conductivity as a float # def get_u_value() # total_conductivity = 0.0 # case self.get_keyword_value("TYPE") # when "LAYERS" # self.get_materials().each do |material_command| # case material_command.get_keyword_value("TYPE") # when "RESISTANCE" # conductivity = 1 / material_command.get_keyword_value("RESISTANCE").to_f # when "PROPERTIES" # conductivity = material_command.get_keyword_value("CONDUCTIVITY").to_f # else # raise "Error in material properties" # end # total_conductivity = total_conductivity + conductivity # end # return total_conductivity # when "U-VALUE" # return self.get_keyword_value("U-VALUE").to_f # end # end # # # end # class DOECommandFactory # def initialize # # end # # def DOECommandFactory.command_factory(command_string, building) # # command = "" # command_name = "" # if (command_string != "") # #Get command and u-value # if ( command_string.match(/(^\s*(\".*?\")\s*\=\s*(\S+)\s*)/) ) # command_name=$3.strip # else # # if no u-value, get just the command. # command_string.match(/(^\s*(\S*)\s)/ ) # @command_name=$2.strip # # end # end # case command_name # when "ZONE" then # command = DOEZone.new() # when "FLOOR" then # command = DOEFloor.new() # when "SPACE" then # command = DOESpace.new() # when "EXTERIOR-WALL" then # command = DOEExteriorWall.new() # when "INTERIOR-WALL" then # command = DOESurface.new() # when "UNDERGROUND-WALL" then # command = DOESurface.new() # when "ROOF" then # command = DOERoof.new() # when "WINDOW" then # command = DOESubSurface.new() # when "DOOR" then # command = DOESubSurface.new() # when "POLYGON" then # command = DOEPolygon.new() # when "LAYER" then # command = DOELayer.new() # when "MATERIAL" then # command = DOEMaterial.new() # when "CONSTRUCTION" then # command = DOEConstruction.new() # else # command = DOECommand.new() # end # # command.get_command_from_string(command_string) # command.building = building # return command # end # end # # # This is the main interface dealing with DOE inp files. You can load, save # # manipulate doe files with this interface at a command level. # class DOEBuilding # # #An array to contain all the DOE # attr_accessor :commands # #An array to contain the current parent when reading in the input files. # attr_accessor :parents # # # # This method makes a deep copy of the building object. # def clone # return Marshal::load(Marshal.dump(self)) # end # # # The Constructor. # def initialize # # @commands=[] # @parents=[] # @commandList = Array.new() # # end # # # This method will find all Commands given the command name string. # # Example # # def find_all_Command("ZONE") will return an array of all the ZONE commands # # used in the building. # def find_all_commands (sCOMMAND) # array = Array.new() # @commands.each do |command| # if (command.commandName == sCOMMAND) # array.push(command) # end # end # return array # end # # # This method will find all Commands given the command name string. # # Example # # def find_all_Command("Default Construction") will return an array of all # # the commands with "Default Construction" as the u-type used in the building. # def find_command_with_utype (utype) # array = Array.new() # @commands.each do |command| # if (command.utype == utype) # array.push(command) # end # end # return array # end # # # # Same as find_all_commands except you can use regular expressions. # def find_all_regex(sCOMMAND) # array = Array.new() # search =/#{sCOMMAND}/ # @commands.each do |command| # if (command.commandName.match(search) ) # array.push(command) # end # # end # return array # end # # # Find a matching keyword value pair in from an array of commands. # # Example: # # find_keyword_value(building.commands, "TYPE", "CONDITIONED") will return # # all the commands that have the # # TYPE = CONDITIONED" # # Keyword pair. # def search_by_keyword_value( keyword, value) # returnarray = Array.new() # @commands.each do |command| # if ( command.keywordPairs[keyword] == value ) # returnarray.push(command) # end # end # return returnarray # end # # # # Will read an input file into memory and store all the commands into the # # commands array. # # param filename # # param runner # def load_inp(filename,runner = nil) # BTAP::runner_register("Info", "loading file:" + filename, runner) # #Open the file. # #puts filename # iter = 0 # # # File.exist?(filename) # f = File.open(filename, "r") # # # # # #Read the file into an array, line by line. # lines = f.readlines # #Set up the temp string. # command_string ="" # # lines.each do|line| # iter = iter.next # #line.forced_encoding("US-ASCII") # #Ignore comments (To do!...strip from file as well as in-line comments. # if (!line.match(/\$.*/) ) # # if (myarray = line.match(/(.*?)\.\./) ) # #Add the last part of the command to the newline...may be blank." # command_string = command_string + myarray[1] # #Determine correct command class to create, then populates it." # command = DOECommandFactory.command_factory(command_string, self) # #Push the command into the command array." # @commands.push(command) # command_string = "" # else # myarray = line.match(/(.*)/) # command_string = command_string + myarray[1] # end # end # end # # organize_data() # BTAP::runner_register("Info","INP model contains:", runner) # #report number of things read in. # ["SPACE","ZONE","EXTERIOR-WALL","ROOF","INTERIOR-WALL","UNDERGROUND-WALL","WINDOW","DOOR","MATERIAL","CONSTRUCTION"].each do |item| # items = self.find_all_commands(item) # message = "\t#{item} = #{items.size}" # BTAP::runner_register("Info",message, runner) # end # BTAP::runner_register("Info", "\tFinished Loading File:" + filename,runner) # end # # # # # This will right a clean output file, meaning no comments. Good for doing # # diffs # def save_inp(string) # array = @commands # w = File.open(string, 'w') # array.each { |command| w.print command.output } # w.close # end # # # # # # #This routine organizes the hierarchy of the space <-> zones and the polygon # # associations that are not formally identified by the sequential relationship # # like the floor, walls, windows. It would seem that zones and spaces are 1 to # # one relationships. So each zone will have a reference to its space and vice versa. # # If there is a polygon command in the space or floor definition, a reference to the # # polygon class will be set. # def organize_data() # # set_envelope_hierarchy # # This method determines the current parents of the current command. # def determine_current_parents(new_command) # if @last_command.nil? # @last_command = new_command # end # #Check to see if scope (HVAC versus Envelope) has changed or the parent depth is undefined "0" # if (!@parents.empty? and (new_command.doe_scope != @parents.last.doe_scope or new_command.depth == 0 )) # @parents.clear # end # #no change in parent. # if ( (new_command.depth == @last_command.depth)) # #no change # @last_command = new_command # #puts "#{new_command.commandName}" # end # #Parent depth added # if ( new_command.depth > @last_command.depth) # @parents.push(@last_command) # #puts "Added parent#{@last_command.commandName}" # @last_command = new_command # end # #parent depth removed. # if ( new_command.depth < @last_command.depth) # parent = @parents.pop # #puts "Removed parent #{parent}" # @last_command = new_command # end # array = Array.new(@parents) # return array # end # # # @commands.each do |command| # if command.doe_scope() == "envelope" # #Sets parents of command. # parents = determine_current_parents(command) # if (!parents.empty?) # command.parents = parents # end # #inserts current command into the parent's children. # if (!command.parents.empty?) # command.parents.last.children.push(command) # end # end # end # # Associating the polygons with the FLoor and spaces. # polygons = find_all_commands("POLYGON") # spaces = find_all_commands("SPACE") # floors = find_all_commands("FLOOR") # zones = find_all_commands("ZONE") # ext_walls = find_all_commands("EXTERIOR-WALL") # roof = find_all_commands("ROOF") # door = find_all_commands("DOOR") # int_walls = find_all_commands("INTERIOR-WALL") # underground_walls = find_all_commands("UNDERGROUND-WALL") # underground_floors = find_all_commands("UNDERGROUND-FLOOR") # constructions =find_all_commands("CONSTRUCTION") # surface_lists = [ ext_walls, roof, door, int_walls, underground_walls, underground_floors] # # # #Organize surface data. # surface_lists.each do |surfaces| # surfaces.each do |surface| # #Assign constructions to surface objects # constructions.each do |construction| # if ( construction.utype == surface.get_keyword_value("CONSTRUCTION") ) # surface.construction = construction # end # end # #Find Polygons associated with surface. # polygons.each do |polygon| # if ( surface.check_keyword?("POLYGON") and polygon.utype == surface.get_keyword_value("POLYGON") ) # surface.polygon = polygon # end # end # end # end # # # # #Organize polygon data for space and floors. # polygons.each do |polygon| # #set up point list in polygon objects # polygon.create_point_list() # #Find Polygons associated with floor and and reference to floor. # floors.each do |floor| # if ( polygon.utype == floor.get_keyword_value("POLYGON") ) # floor.polygon = polygon # end # end # #Find Polygons for space and add reference to the space. # spaces.sort.each do |space| # if space.check_keyword?("POLYGON") # if ( polygon.utype == space.get_keyword_value("POLYGON") ) # space.polygon = polygon # end # end # end # end # # # # # Find spaces that belong to the zone. # zones.each do |zone| # spaces.sort.each do |space| # if ( space.utype == zone.get_keyword_value("SPACE") ) # space.zone = zone # zone.space = space # end # end # end # end # # # # def get_building_transformation_matrix() # build_params = self.find_all_commands("BUILD-PARAMETERS")[0] # building_xref = build_params.check_keyword?("X-REF")? build_params.get_keyword?("X-REF") : 0.0 # building_yref = build_params.check_keyword?("Y-REF")? build_params.get_keyword?("Y-REF") : 0.0 # building_origin = OpenStudio::Vector3d.new(building_xref,building_yref,0.0) # building_azimuth = build_params.check_keyword?("AZIMUTH")? build_params.get_keyword?("AZIMUTH") : 0.0 # return OpenStudio::Transformation::rotation(OpenStudio::Vector3d(0.0, 0.0, 1.0), openstudio::degToRad(building_azimuth)) * OpenStudio::Transformation::translation(building_origin) # end # # # # # #this method will convert a DOE inp file to the OSM file.. This will return # # and openstudio model object. # def create_openstudio_model_new(runner = nil) # beginning_time = Time.now # # end_time = Time.now # BTAP::runner_register("Info", "Time elapsed #{(end_time - beginning_time)*1000} milliseconds",runner) # model = OpenStudio::Model::Model.new() # #add All Materials # # find_all_commands( "Materials" ).each do |doe_material| # # end # # # # find_all_commands( "Constructions" ).each do |doe_cons| # # end # # #this block will create OS story objects in the OS model. # BTAP::runner_register("Info", "Exporting DOE FLOORS to OS",runner) # find_all_commands("FLOOR").each do |doe_floor| # doe_floor.convert_to_openstudio(model) # end # BTAP::runner_register("Info", OpenStudio::Model::getBuildingStorys(model).size.to_s + " floors created",runner) # # #this block will create OS space objects in the OS model. # BTAP::runner_register("Info", "Exporting DOE SPACES to OS",runner) # find_all_commands("SPACE").each do |doe_space| # doe_space.convert_to_openstudio(model) # end # BTAP::runner_register("Info", OpenStudio::Model::getSpaces(model).size.to_s + " spaces created",runner) # # #this block will create OS space objects in the OS model. # BTAP::runner_register("Info", "Exporting DOE ZONES to OS",runner) # find_all_commands("ZONE").each do |doe_zone| # doe_zone.convert_to_openstudio(model) # end # BTAP::runner_register("Info", OpenStudio::Model::getThermalZones(model).size.to_s + " zones created",runner) # # #this block will create OS surface objects in the OS model. # BTAP::runner_register("Info", "Exporting DOE Surfaces to OS",runner) # all_surfaces = Array.new() # @commands.each do |command| # case command.commandName # when "EXTERIOR-WALL","INTERIOR-WALL","UNDERGROUND-WALL","ROOF" # all_surfaces.push(command) # end # end # all_surfaces.each do |doe_surface| # doe_surface.convert_to_openstudio(model) # end # BTAP::runner_register("Info", OpenStudio::Model::getSurfaces(model).size.to_s + " surfaces created",runner) # BTAP::runner_register("Info", OpenStudio::Model::getSubSurfaces(model).size.to_s + " sub_surfaces created",runner) # BTAP::runner_register("Info", "Setting Boundary Conditions for surfaces",runner) # BTAP::Geometry::match_surfaces(model) # # x_scale = y_scale = z_scale = 0.3048 # BTAP::runner_register("Info", "scaling model from feet to meters",runner) # model.getPlanarSurfaces.sort.each do |surface| # new_vertices = OpenStudio::Point3dVector.new # surface.vertices.each do |vertex| # new_vertices << OpenStudio::Point3d.new(vertex.x * x_scale, vertex.y * y_scale, vertex.z * z_scale) # end # surface.setVertices(new_vertices) # end # # model.getPlanarSurfaceGroups.sort.each do |surface_group| # transformation = surface_group.transformation # translation = transformation.translation # euler_angles = transformation.eulerAngles # new_translation = OpenStudio::Vector3d.new(translation.x * x_scale, translation.y * y_scale, translation.z * z_scale) # #TODO these might be in the wrong order # new_transformation = OpenStudio::createRotation(euler_angles) * OpenStudio::createTranslation(new_translation) # surface_group.setTransformation(new_transformation) # end # BTAP::runner_register("Info", "DOE2.2 -> OS Geometry Conversion Complete",runner) # BTAP::runner_register("Info", "Summary of Conversion",runner) # BTAP::runner_register("Info", OpenStudio::Model::getBuildingStorys(model).size.to_s + " floors created",runner) # BTAP::runner_register("Info", OpenStudio::Model::getSpaces(model).size.to_s + " spaces created",runner) # BTAP::runner_register("Info", OpenStudio::Model::getThermalZones(model).size.to_s + " thermal zones created",runner) # BTAP::runner_register("Info", OpenStudio::Model::getSurfaces(model).size.to_s + " surfaces created",runner) # BTAP::runner_register("Info", OpenStudio::Model::getSubSurfaces(model).size.to_s + " sub_surfaces created",runner) # BTAP::runner_register("Info", "No Contruction were converted.",runner) # BTAP::runner_register("Info", "No Materials were converted",runner) # BTAP::runner_register("Info", "No HVAC components were converted",runner) # BTAP::runner_register("Info", "No Environment or Simulation setting were converted.",runner) # # end_time = Time.now # BTAP::runner_register("Info", "Time elapsed #{(end_time - beginning_time)} seconds",runner) # return model # end # # # # # # def get_materials() # BTAP::runner_register("Info", "Spaces",runner) # find_all_commands("SPACE").each do |space| # BTAP::runner_register("Info", space.get_azimuth(),runner) # end # BTAP::runner_register("Info", "Materials",runner) # find_all_commands("MATERIAL").each do |materials| # BTAP::runner_register("Info", materials.get_name(),runner) # end # BTAP::runner_register("Info", "Layers",runner) # find_all_commands("LAYERS").each do |materials| # BTAP::runner_register("Info", materials.get_name(),runner) # end # BTAP::runner_register("Info", "Constructions",runner) # find_all_commands("CONSTRUCTION").each do |materials| # BTAP::runner_register("Info", materials.get_name(),runner) # end # # end # # # end # # This class will manage all the layer information of the Reference components. # class LayerManager # include Singleton # class Layer # # attr_accessor :name # attr_accessor :thickness # attr_accessor :conductivity # attr_accessor :density # attr_accessor :specific_heat # attr_accessor :air_space # attr_accessor :resistance # def initialize # @air_space = false # end # # def set( thickness, conductivity, density, specific_heat) # @thickness, @conductivity, @density, @specific_heat = thickness, conductivity, density, specific_heat # @airspace = false # end # # def set_air_space(thickness, resistance) # @thickness, @resistance = thickness, resistance # @air_space = true # end # # def output # string = "Airspace = #{@air_space}\nThickness = #{@thickness}\nConductivity = #{@conductivity}\nResistance = #{@resistance}\nDensity = #{@density}\nSpecificHeat = #{@specific_heat}\n" # end # end # # Array of all the layers # attr_accessor :layers # def initialize # @layers = Array.new() # end # # #Add a layer. If the layer already exists. It will return the exi # def add_layer(new_layer) # #first determine if the layer already exists. # @layers.each do |current_layer| # if new_layer == current_layer # return current_layer # end # end # @layers.push(new_layer) # return @layers.last() # end # # private # # def clear() # @layers.clear() # end # end # #This class manages all of the constructions that are used in the simulation. It # #should remove any constructions that are doubly defined in the project. # class ConstructionManager # # An array containing all the constructions. # attr_accessor :constructions # # # The layer manager all the constructions. # attr_accessor :layer_manager # class Construction # # #The unique name for the construction. # attr_accessor :name # #The array which contains the material layers of the construction. # attr_accessor :layers # # def initialize # #Set up the array for the layers. # @layers = Array.new() # end # # #Adds a layer object to the construction. # # Must pass a Layer object as an arg. # def add_layer_object( object ) # layers.push( object ) # end # # #Adds a layer based on the physical properties list. # #All units are based on the simulators input. # def add_layer(thickness, conductivity, density, specific_heat) # layer = Layer.new() # # Make sure all the values are > 0. # layer.set(thickness, conductivity, density, specific_heat) # @layers.push(layer) # end # # # Adds an airspace to the construction based on the thickness and Resistances. # #All units are based on the simulators input. # def add_air_space(thickness, resistance ) # layer = Layer.new() # layer.set_air_space(thickness, resistance) # @layers.push(layer) # end # # def output() # soutput = "" # @layers.each do|layer| # soutput = soutput + layer.output() + "\n" # end # soutput # end # end # # # def initialize # @constructions = Array.new() # @layer_manager = LayerManager.instance() # end # # # #Adds a new construction to the construction array. # #Arg must be a construction object. # def add_construction(new_construction) # #first determine if the layer already exists. # @constructions.each do |current_construction| # if new_construction == current_construction # return current_construction # end # end # new_construction.layers.each do |new_layer| # #If the new layer already exists...use the old one instead. # # it is the layerManager's job to decide this. # new_layer = @layer_manager.add_layer(new_layer) # end # @constructions.push(new_construction) # return @constructions.last() # end # # def clear() # @constructions.clear() # @layer_manager.clear() # end # # end # end # end #