Skip to content

Commit

Permalink
Merge pull request #28 from urbanopt/develop_iit
Browse files Browse the repository at this point in the history
Develop iit
  • Loading branch information
kflemin authored Nov 15, 2022
2 parents eae191c + f6f7400 commit 6c74858
Show file tree
Hide file tree
Showing 12 changed files with 1,508 additions and 253 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,6 @@ runner.conf
# ignore template files for now
/template_inputs/*
test_opendss_catalog.json
*.sql
*.sql

*__pycache__
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,21 @@ bundle exec rake create_opendss_catalog[/desired/path/to/opendss_catalog.json]
| API Version | RNM-US Gem Version | RNM-US exe Version |
| ----------- | ----------- | ---------------- |
| v1 | 0.3.0 and earlier | RNM-US_20220819 |
| v2 | 0.4.0 | RNM-US_20220927 |
| v2 | 0.4.0 | RNM-US_20221018 |


## Validation Functionality

The validation and results visualization functionality is written in python. Follow these steps if you would like to use it.

1. Install python (3.10) if you do not already have it installed
1. Clone the repo to your computer
1. cd into the repo directory
1. run `bundle install` to install the required ruby dependencies
1. run `pip install -r requirements.txt` to install the required python dependencies for the validation module
1. create input files and run the simulation as usual
1. run `bundle exec rake run_validation[/path/to/scenario/csv]` to run the validation


## Testing

Expand Down
37 changes: 31 additions & 6 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,29 @@ task :run_simulation, [:scenario_csv_path, :reopt, :use_localhost] do |t, args|
puts '...done!'
end

# Full Runner workflow (mimics UO CLI functionality)
# pass in the path to the scenario csv, geojson path, whether this is a reopt analysis (true/false), and whether to use localhost RNM API (true/false)
desc 'Full Runner workflow'
task :full_runner_workflow, [:scenario_csv_path, :geojson_path, :reopt, :use_localhost] do |t, args|
# todo: could allow passing in extended catalog, average peak catalog, and opendss_catalog flags too
# if no path passed in, use default:
scenario_csv = args[:scenario_csv_path] || 'spec/test/example_project/run/baseline_scenario'
geojson_path = args[:geojson_path] || 'spec/test/example_project/example_project_with_network_and_streets'
root_dir, scenario_file_name = File.split(File.expand_path(scenario_csv))
scenario_name = File.basename(scenario_file_name, File.extname(scenario_file_name))
run_dir = File.join(root_dir, 'run', scenario_name.downcase)
reopt = args[:reopt] || false
reopt = reopt == 'true'
use_local = args[:use_localhost] || false

runner = URBANopt::RNM::Runner.new(scenario_name, run_dir, scenario_csv, geojson_path, reopt: reopt)
runner.create_simulation_files
runner.run(use_local)
runner.post_process

puts '...done!'
end

# Create opendss catalog from extended catalog
# pass in the path and filename where the OpenDSS catalog should be saved
desc 'Create OpenDSS catalog'
Expand All @@ -169,28 +192,30 @@ end
# run validation
# pass in the path to the scenario csv
desc 'Run Validation'
task :run_validation, [:scenario_csv_path, :reopt, :use_localhost] do |t, args|
task :run_validation, [:scenario_csv_path, :use_numeric_ids] do |t, args|
#Exammple to run validation
#bundle exec rake run_validation[D:/.../urbanopt-rnm-us-gem/spec/files/example_project/baseline_scenario.csv]
#bundle exec rake run_validation[D:/.../urbanopt-rnm-us-gem/spec/files/example_project/baseline_scenario.csv,true]

puts 'Running OpenDSS validation'

# if no path passed in, use default:
scenario_csv = args[:scenario_csv_path] || 'spec/test/example_project/run/baseline_scenario'
root_dir, scenario_file_name = File.split(File.expand_path(scenario_csv))
scenario_name = File.basename(scenario_file_name, File.extname(scenario_file_name))
run_dir = File.join(root_dir, 'run', scenario_name.downcase)

rnm_dir = File.join(run_dir, 'rnm-us')



#Use numeric ids (for the hierarchical plot of the network)
use_numeric_ids = args[:use_numeric_ids] || false
use_numeric_ids = use_numeric_ids == 'true'

if !File.exist?(rnm_dir)
puts rnm_dir
raise 'No rnm-us directory found for this scenario...run the create_inputs rake task first.'
end

puts "run dir path: #{run_dir}"
validation = URBANopt::RNM::Validation.new(rnm_dir)
validation = URBANopt::RNM::Validation.new(rnm_dir,use_numeric_ids)
validation.run_validation()

puts '...done!'
Expand Down
16 changes: 14 additions & 2 deletions lib/urbanopt/rnm/consumers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
module URBANopt
module RNM
class Consumers
attr_accessor :customers, :customers_ext, :profile_customer_p, :profile_customer_q, :profile_customer_p_ext, :profile_customer_q_ext, :power_factor
attr_accessor :customers, :customers_ext, :profile_customer_p, :profile_customer_q, :profile_customer_p_ext, :profile_customer_q_ext, :power_factor, :profile_date_time, :profile_date_time_ext

# initializing all the attributes to build the inputs files required by the RNM-US model
def initialize(reopt, only_lv_consumers = false, max_num_lv_nodes, average_building_peak_catalog_path, lv_limit)
Expand All @@ -55,8 +55,10 @@ def initialize(reopt, only_lv_consumers = false, max_num_lv_nodes, average_build
@max_num_lv_nodes = max_num_lv_nodes
@customers = []
@customers_ext = []
@profile_date_time = []
@profile_customer_p = []
@profile_customer_q = []
@profile_date_time_ext = []
@profile_customer_p_ext = []
@profile_customer_q_ext = []
@power_factor = power_factor
Expand All @@ -73,8 +75,10 @@ def initialize(reopt, only_lv_consumers = false, max_num_lv_nodes, average_build
# while the 2nd option is run in case "only LV" set to false and the consumption for each building will be placed in a single node
def construct_consumer(profiles, single_values, building_map, building_nodes, height, users, folder)
if @only_lv_consumers
planning_date_time = []
planning_profile_node_active = []
planning_profile_node_reactive = []
yearly_date_time = []
yearly_profile_node_active = []
yearly_profile_node_reactive = []
nodes_per_bldg, area, medium_voltage = av_peak_cons_per_building_type(folder['building_types'])
Expand Down Expand Up @@ -106,19 +110,23 @@ def construct_consumer(profiles, single_values, building_map, building_nodes, he
else
voltage_default, phases = voltage_values(peak_active_power_cons / @power_factor)
end

for k in 0..profiles[:planning_profile_cust_active].length - 1
planning_date_time[k]=profiles[:planning_date_time][k]
planning_profile_node_active[k] = ((profiles[:planning_profile_cust_active][k]) / nodes_per_bldg).round(2)
planning_profile_node_reactive[k] = ((profiles[:planning_profile_cust_reactive][k]) / nodes_per_bldg).round(2)
end
for k in 0..profiles[:yearly_profile_cust_active].length - 1
yearly_date_time[k]=profiles[:yearly_date_time][k]
yearly_profile_node_active[k] = ((profiles[:yearly_profile_cust_active][k]) / nodes_per_bldg).round(2)
yearly_profile_node_reactive[k] = ((profiles[:yearly_profile_cust_reactive][k]) / nodes_per_bldg).round(2)
end
@customers.push([coordinates, voltage_default, peak_active_power_cons, peak_reactive_power_cons, phases])
@customers_ext.push([coordinates, voltage_default, peak_active_power_cons, peak_reactive_power_cons, phases, area, height, (single_values[:energy] / nodes_per_bldg).round(2), peak_active_power_cons, peak_reactive_power_cons, users])
@profile_date_time.push([planning_date_time])
@profile_customer_q.push([id, 24, planning_profile_node_reactive])
@profile_customer_p.push([id, 24, planning_profile_node_active])
@profile_date_time_ext.push([yearly_date_time])
@profile_customer_p_ext.push([id, 8760, yearly_profile_node_active])
@profile_customer_q_ext.push([id, 8760, yearly_profile_node_reactive])

Expand All @@ -131,8 +139,10 @@ def construct_consumer(profiles, single_values, building_map, building_nodes, he
voltage_default, phases = voltage_values(single_values[:peak_active_power_cons] / @power_factor * 0.9) # applying safety factor
@customers.push([building_map, voltage_default, single_values[:peak_active_power_cons], single_values[:peak_reactive_power_cons], phases])
@customers_ext.push([building_map, voltage_default, single_values[:peak_active_power_cons], single_values[:peak_reactive_power_cons], phases, area, height, (single_values[:energy]).round(2), single_values[:peak_active_power_cons], single_values[:peak_reactive_power_cons], users])
@profile_date_time.push([profiles[:planning_date_time]])
@profile_customer_q.push([id, 24, profiles[:planning_profile_cust_reactive]])
@profile_customer_p.push([id, 24, profiles[:planning_profile_cust_active]])
@profile_date_time_ext.push([profiles[:yearly_date_time]])
@profile_customer_p_ext.push([id, 8760, profiles[:yearly_profile_cust_active]])
@profile_customer_q_ext.push([id, 8760, profiles[:yearly_profile_cust_reactive]])
end
Expand Down Expand Up @@ -234,10 +244,12 @@ def customer_files_load(csv_feature_report, json_feature_report, building_map, b
# content = CSV.foreach(csv_feature_report, headers: true) do |power|
CSV.foreach(csv_feature_report, headers: true) do |power|
@power_factor = power['Electricity:Facility Power(kW)'].to_f / power['Electricity:Facility Apparent Power(kVA)'].to_f
profiles[:yearly_date_time].push(power['Datetime'])
profiles[:yearly_profile_cust_active].push(power['Electricity:Facility Power(kW)'].to_f)
profiles[:yearly_profile_cust_reactive].push(profiles[:yearly_profile_cust_active][k] * Math.tan(Math.acos(@power_factor)))
single_values[:energy] += power['REopt:Electricity:Load:Total(kw)'].to_f # calculating the yearly energy consumed by each feature
if k >= profile_start_max && k <= profile_start_max + hours
profiles[:planning_date_time].push(power['Datetime'])
profiles[:planning_profile_cust_active].push(power['Electricity:Facility Power(kW)'].to_f)
if power['Electricity:Facility Power(kW)'].to_f > single_values[:peak_active_power_cons]
single_values[:peak_active_power_cons] = power['Electricity:Facility Power(kW)'].to_f
Expand Down
18 changes: 18 additions & 0 deletions lib/urbanopt/rnm/input_files.rb
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,10 @@ def create
File.open(File.join(@run_dir, @rnm_dirname, 'customers_ext.txt'), 'w+') do |g|
g.puts(prosumers.customers_ext.map { |w| w.join(';') })
end
File.open(File.join(@run_dir, @rnm_dirname, 'timestamps.csv'), 'w+') do |g|
g.puts("Datetime\n")
g.puts(prosumers.profile_date_time[0].map { |w| w.join("\n") })
end
File.open(File.join(@run_dir, @rnm_dirname, 'cust_profile_p.txt'), 'w+') do |g|
g.puts(prosumers.profile_customer_p.map { |w| w.join(';') })
end
Expand All @@ -267,6 +271,10 @@ def create
# CSV.open(File.join(@run_dir, @rnm_dirname, "cust_profile_q_extendido.csv"), "w") do |csv|
# csv << [prosumers.profile_customer_q_ext]
# end
File.open(File.join(@run_dir, @rnm_dirname, 'timestamps_extendido.csv'), 'w+') do |g|
g.puts("Datetime\n")
g.puts(prosumers.profile_date_time_ext[0].map { |w| w.join("\n") })
end
File.open(File.join(@run_dir, @rnm_dirname, 'cust_profile_q_extendido.txt'), 'w+') do |g|
g.puts(prosumers.profile_customer_q_ext.map { |w| w.join(';') })
end
Expand All @@ -289,6 +297,7 @@ def create
File.open(File.join(@run_dir, @rnm_dirname, 'gen_profile_p_extendido.txt'), 'w+') do |g|
g.puts(prosumers.profile_dg_p_extended.map { |w| w.join(';') })
end
ficheros_entrada_inc.push('Timestamps;timestamps.csv;timestamps_extendido.csv')
ficheros_entrada_inc.push('CClienteGreenfield;customers_ext.txt;cust_profile_p.txt;cust_profile_q.txt;cust_profile_p_extendido.txt;cust_profile_q_extendido.txt')
ficheros_entrada_inc.push('CGeneradorGreenfield;generators.txt;gen_profile_p.txt;gen_profile_q.txt;gen_profile_p_extendido.txt;gen_profile_q_extendido.txt')
ficheros_entrada_inc.push('END')
Expand All @@ -302,18 +311,27 @@ def create
File.open(File.join(@run_dir, @rnm_dirname, 'customers_ext.txt'), 'w+') do |g|
g.puts(consumers.customers_ext.map { |w| w.join(';') })
end
File.open(File.join(@run_dir, @rnm_dirname, 'timestamps.csv'), 'w+') do |g|
g.puts("Datetime\n")
g.puts(consumers.profile_date_time[0].map { |w| w.join("\n") })
end
File.open(File.join(@run_dir, @rnm_dirname, 'cust_profile_p.txt'), 'w+') do |g|
g.puts(consumers.profile_customer_p.map { |w| w.join(';') })
end
File.open(File.join(@run_dir, @rnm_dirname, 'cust_profile_q.txt'), 'w+') do |g|
g.puts(consumers.profile_customer_q.map { |w| w.join(';') })
end
File.open(File.join(@run_dir, @rnm_dirname, 'timestamps_extendido.csv'), 'w+') do |g|
g.puts("Datetime\n")
g.puts(consumers.profile_date_time_ext[0].map { |w| w.join("\n") })
end
File.open(File.join(@run_dir, @rnm_dirname, 'cust_profile_q_extendido.txt'), 'w+') do |g|
g.puts(consumers.profile_customer_q_ext.map { |w| w.join(';') })
end
File.open(File.join(@run_dir, @rnm_dirname, 'cust_profile_p_extendido.txt'), 'w+') do |g|
g.puts(consumers.profile_customer_p_ext.map { |w| w.join(';') })
end
ficheros_entrada_inc.push('Timestamps;timestamps.csv;timestamps_extendido.csv')
ficheros_entrada_inc.push('CClienteGreenfield;customers_ext.txt;cust_profile_p.txt;cust_profile_q.txt;cust_profile_p_extendido.txt;cust_profile_q_extendido.txt')
ficheros_entrada_inc.push('END')
File.open(File.join(@run_dir, @rnm_dirname, 'ficheros_entrada_inc.txt'), 'w+') do |g|
Expand Down
Loading

0 comments on commit 6c74858

Please sign in to comment.