Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Appx g/feature/export user data partial #1611

Merged
merged 7 commits into from
Sep 21, 2023
Merged
1 change: 1 addition & 0 deletions lib/openstudio-standards.rb
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ module OpenstudioStandards
require_relative "#{stds}/ashrae_90_1_prm/ashrae_90_1_prm.Surface"
require_relative "#{stds}/ashrae_90_1_prm/ashrae_90_1_prm.DesignSpecificationOutdoorAir"
require_relative "#{stds}/ashrae_90_1_prm/userdata_csv/userdata_enums.rb"
require_relative "#{stds}/ashrae_90_1_prm/userdata_csv/ashrae_90_1_prm.UserData"

# 90.1-PRM-2019
require_relative "#{stds}/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019"
Expand Down
8 changes: 6 additions & 2 deletions lib/openstudio-standards/standards/Standards.Model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,11 @@ def model_create_prm_proposed_building(user_model)
# If needed, modify user model infiltration
if user_buildings
user_building_index = user_buildings.index { |user_building| building_name.include? user_building['name'] }
infiltration_modeled_from_field_verification_results = user_buildings[user_building_index]['infiltration_modeled_from_field_verification_results'].to_s.downcase
# TODO Move the user data processing section
infiltration_modeled_from_field_verification_results = 'false'
if user_building_index && user_buildings[user_building_index]['infiltration_modeled_from_field_verification_results']
infiltration_modeled_from_field_verification_results = user_buildings[user_building_index]['infiltration_modeled_from_field_verification_results'].to_s.downcase
end

# Calculate total infiltration flow rate per envelope area
building_envelope_area_m2 = model_building_envelope_area(proposed_model)
Expand All @@ -594,7 +598,7 @@ def model_create_prm_proposed_building(user_model)

# Warn users if the infiltration modeling in the user/proposed model is not based on field verification
# If not modeled based on field verification, it should be modeled as 0.6 cfm/ft2
unless infiltration_modeled_from_field_verification_results.casecmp('Yes')
unless infiltration_modeled_from_field_verification_results.casecmp('true')
if curr_tot_infil_cfm_per_envelope_area < 0.6
OpenStudio.logFree(OpenStudio::Info, 'prm.log', "The user model's I_75Pa is estimated to be #{curr_tot_infil_cfm_per_envelope_area} m3/s per m2 of total building envelope")
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2393,7 +2393,6 @@ def get_baseline_system_groups_for_one_building_type(model, hvac_building_type,

# Consider special rules for computer rooms
# need load of all

# Get cooling load of all computer rooms to establish system types
comp_room_loads = {}
bldg_comp_room_load = 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,34 @@ def load_standards_database(data_directories = [])
super([__dir__] + data_directories)
end

# Method to generate user data from a user model and save the csvs to the user_data_path
# This method can generate one user data csv based on the matching name or a full set of user data if
# leave it as nil
# @param user_model [OpenStudio::Model::Model] OpenStudio model object
# @param user_data_path [String] data path
# @param user_data_file [String] the name of the user data file.
def generate_userdata_to_csv(user_model, user_data_path, user_data_file = nil)
user_data_list = [UserDataCSVAirLoopHVAC.new(user_model, user_data_path),
UserDataCSVBuilding.new(user_model, user_data_path),
UserDataCSVSpace.new(user_model, user_data_path),
UserDataCSVSpaceTypes.new(user_model, user_data_path),
UserDataCSVAirLoopHVACDOAS.new(user_model, user_data_path),
UserDataCSVExteriorLights.new(user_model, user_data_path),
UserDataCSVThermalZone.new(user_model, user_data_path),
UserDataCSVElectricEquipment.new(user_model, user_data_path),
UserDataCSVOutdoorAir.new(user_model, user_data_path)]

if user_data_file.nil?
user_data_list.each {|user_data| user_data.write_csv}
else
user_data_list.each do |user_data|
if user_data.file_name == user_data_file
user_data.write_csv
end
end
end
end

# Convert user data csv files to json format and save to project folder
# Method will create the json_folder in the project_path
# @author Doug Maddox, PNNL
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
class UserDataCSV
# Abstract class for writing user data template from user model.
#
# @param model [OpenStudio::Model::Model]
# @param save_dir [String] directory to save user data files
def initialize(model, save_dir)
weilixu marked this conversation as resolved.
Show resolved Hide resolved
@model = model
@component_name = nil
unless Dir.exist?(save_dir)
raise ArgumentError "Saving directory #{save_dir} does not exist!"
end
@save_dir = save_dir
@components = nil
@headers = nil
@file_name = nil
end

# getter function to get file name
def file_name
@file_name
end

# method to write csv files
# this method controls the workflow for generating a user data file.
# @return [Boolean] True for success, false otherwise
def write_csv
@components = load_component
@headers = load_header
unless @components
OpenStudio.logFree(OpenStudio::Warn, 'prm.log', "No relevant component #{@component_name} found in model. Skip the process")
return false
end

CSV.open("#{@save_dir}/#{@file_name}.csv", 'w') do |csv|
csv << @headers
@components.each do |component|
csv << [prm_get_component_name(component)] + write_default_rows
end
end
return true
end

private

# method to write the parameters in the csv file.
# This method provides a template to write in default values to the user data file
# return [Array] array of strings that contains the data in the userdata file
def write_default_rows
raise NotImplementedError, 'Method write rows should be implemented in class'
end

# Load header from pre-defined user data files.
# This method loads the user data file from the list.
#
# @return [Boolean] true if success, false otherwise.
def load_header
userdata_dir = __dir__
src_csv_dir = "#{userdata_dir}/*.csv"
headers = nil
Dir.glob(src_csv_dir).each do |csv_full_name|
csv_file_name = File.basename(csv_full_name, File.extname(csv_full_name))
if csv_file_name == @file_name
headers = CSV.read(csv_full_name, headers: true).headers
end
end
return headers
end

# Method to load OpenStudio component list from the model and save to @Component
# subclass shall determine what data group to extract from a modle.
# @return [Array] array of OpenStudio components.
def load_component
return @model.public_send("get#{@component_name}")
end
end

class UserDataCSVAirLoopHVAC < UserDataCSV
# user data userdata_airloop_hvac
# @param model [OpenStudio::Model::Model]
# @param save_dir [String] directory to save user data files
def initialize(model, save_dir)
weilixu marked this conversation as resolved.
Show resolved Hide resolved
super
@component_name = 'AirLoopHVACs'
@file_name = UserDataFiles::AIRLOOP_HVAC
end

def write_default_rows
# TODO we can do more here but right now, keep everything unchecked.
return Array.new(@headers.length - 1, '')
end
end

class UserDataCSVBuilding < UserDataCSV
# user data userdata_building
# @param model [OpenStudio::Model::Model]
# @param save_dir [String] directory to save user data files
def initialize(model, save_dir)
weilixu marked this conversation as resolved.
Show resolved Hide resolved
super
@component_name = 'Building'
@file_name = UserDataFiles::BUILDING
end

private

def load_component
return [@model.public_send("get#{@component_name}")]
end

def write_default_rows
# TODO we can do more here but right now, keep everything unchecked.
return Array.new(@headers.length - 1, '')
end
end

class UserDataCSVSpace < UserDataCSV
# user data userdata_space
# @param model [OpenStudio::Model::Model]
# @param save_dir [String] directory to save user data files
def initialize(model, save_dir)
super
@component_name = 'Spaces'
@file_name = UserDataFiles::SPACE
end

private

def write_default_rows
# TODO we can do more here but right now, keep everything unchecked.
return Array.new(@headers.length - 1, '')
end
end

class UserDataCSVSpaceTypes < UserDataCSV
# user data userdata_spacetypes
# @param model [OpenStudio::Model::Model]
# @param save_dir [String] directory to save user data files
def initialize(model, save_dir)
super
@component_name = 'SpaceTypes'
@file_name = UserDataFiles::SPACETYPE
end

private

def write_default_rows
# TODO we can do more here but right now, keep everything unchecked.
return Array.new(@headers.length - 1, '')
end
end

class UserDataCSVAirLoopHVACDOAS < UserDataCSV
# user data userdata_airloop_hvac_doas
# @param model [OpenStudio::Model::Model]
# @param save_dir [String] directory to save user data files
def initialize(model, save_dir)
super
@component_name = 'AirLoopHVACDedicatedOutdoorAirSystems'
@file_name = UserDataFiles::AIRLOOP_HVAC_DOAS
end

def write_default_rows
# TODO we can do more here but right now, keep everything unchecked.
return Array.new(@headers.length - 1, '')
end
end

class UserDataCSVExteriorLights < UserDataCSV
# user data userdata_airloop_hvac_doas
# @param model [OpenStudio::Model::Model]
# @param save_dir [String] directory to save user data files
def initialize(model, save_dir)
super
@component_name = 'ExteriorLightss'
@file_name = UserDataFiles::EXTERIOR_LIGHTS
end

def write_default_rows
# TODO we can do more here but right now, keep everything unchecked.
return Array.new(@headers.length - 1, '')
end
end

class UserDataCSVThermalZone < UserDataCSV
# user data userdata_thermal_zone
# @param model [OpenStudio::Model::Model]
# @param save_dir [String] directory to save user data files
def initialize(model, save_dir)
super
@component_name = 'ThermalZones'
@file_name = UserDataFiles::THERMAL_ZONE
end

def write_default_rows
# TODO we can do more here but right now, keep everything unchecked.
return Array.new(@headers.length - 1, '')
end
end

class UserDataCSVElectricEquipment < UserDataCSV
# user data userdata_electric_equipment
# @param model [OpenStudio::Model::Model]
# @param save_dir [String] directory to save user data files
def initialize(model, save_dir)
super
@component_name = 'ElectricEquipments'
@file_name = UserDataFiles::ELECTRIC_EQUIPMENT
end

def write_default_rows
# TODO we can do more here but right now, keep everything unchecked.
return Array.new(@headers.length - 1, '')
end
end

class UserDataCSVOutdoorAir < UserDataCSV
# user data userdata_design_specification_outdoor_air
# @param model [OpenStudio::Model::Model]
# @param save_dir [String] directory to save user data files
def initialize(model, save_dir)
super
@component_name = 'DesignSpecificationOutdoorAirs'
@file_name = UserDataFiles::DESIGN_SPECIFICATION_OUTDOOR_AIR
end

def write_default_rows
# TODO we can do more here but right now, keep everything unchecked.
return Array.new(@headers.length - 1, '')
end
end