urbanopt-rnm-us 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +32 -0
- data/.rubocop.yml +9 -0
- data/CHANGELOG.md +5 -0
- data/CONTRIBUTING.md +58 -0
- data/Gemfile +10 -0
- data/LICENSE.md +38 -0
- data/README.md +49 -0
- data/Rakefile +166 -0
- data/catalogs/average_peak_per_building_type.json +94 -0
- data/catalogs/extended_catalog.json +15109 -0
- data/lib/urbanopt-rnm.rb +41 -0
- data/lib/urbanopt/rnm.rb +59 -0
- data/lib/urbanopt/rnm/api_client.rb +296 -0
- data/lib/urbanopt/rnm/capacitor_opendss.rb +57 -0
- data/lib/urbanopt/rnm/carson_eq.rb +389 -0
- data/lib/urbanopt/rnm/consumers.rb +255 -0
- data/lib/urbanopt/rnm/conversion_to_opendss.rb +152 -0
- data/lib/urbanopt/rnm/geojson_input.rb +261 -0
- data/lib/urbanopt/rnm/input_files.rb +335 -0
- data/lib/urbanopt/rnm/logger.rb +52 -0
- data/lib/urbanopt/rnm/oh_ug_rate.rb +129 -0
- data/lib/urbanopt/rnm/post_processor.rb +220 -0
- data/lib/urbanopt/rnm/processor_opendss_catalog.rb +73 -0
- data/lib/urbanopt/rnm/prosumers.rb +372 -0
- data/lib/urbanopt/rnm/rnm_us_catalog_conversion.rb +140 -0
- data/lib/urbanopt/rnm/runner.rb +177 -0
- data/lib/urbanopt/rnm/scenario_report.rb +145 -0
- data/lib/urbanopt/rnm/substation_location.rb +63 -0
- data/lib/urbanopt/rnm/transformer_opendss.rb +67 -0
- data/lib/urbanopt/rnm/version.rb +45 -0
- data/lib/urbanopt/rnm/wires_class.rb +70 -0
- data/lib/urbanopt/rnm/wires_opendss.rb +93 -0
- data/urbanopt-rnm-us-gem.gemspec +37 -0
- metadata +218 -0
@@ -0,0 +1,177 @@
|
|
1
|
+
# *********************************************************************************
|
2
|
+
# URBANopt (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
|
3
|
+
# contributors. All rights reserved.
|
4
|
+
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
# are permitted provided that the following conditions are met:
|
7
|
+
|
8
|
+
# Redistributions of source code must retain the above copyright notice, this list
|
9
|
+
# of conditions and the following disclaimer.
|
10
|
+
|
11
|
+
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
|
+
# list of conditions and the following disclaimer in the documentation and/or other
|
13
|
+
# materials provided with the distribution.
|
14
|
+
|
15
|
+
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
|
+
# used to endorse or promote products derived from this software without specific
|
17
|
+
# prior written permission.
|
18
|
+
|
19
|
+
# Redistribution of this software, without modification, must refer to the software
|
20
|
+
# by the same designation. Redistribution of a modified version of this software
|
21
|
+
# (i) may not refer to the modified version by the same designation, or by any
|
22
|
+
# confusingly similar designation, and (ii) must refer to the underlying software
|
23
|
+
# originally provided by Alliance as "URBANopt". Except to comply with the foregoing,
|
24
|
+
# the term "URBANopt", or any confusingly similar designation may not be used to
|
25
|
+
# refer to any modified version of this software or any modified version of the
|
26
|
+
# underlying software originally provided by Alliance without the prior written
|
27
|
+
# consent of Alliance.
|
28
|
+
|
29
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
30
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
31
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
32
|
+
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
33
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
34
|
+
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
35
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
36
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
37
|
+
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
38
|
+
# OF THE POSSIBILITY OF SUCH DAMAGE.
|
39
|
+
# *********************************************************************************
|
40
|
+
|
41
|
+
require 'csv'
|
42
|
+
require 'urbanopt/rnm/logger'
|
43
|
+
|
44
|
+
module URBANopt
|
45
|
+
module RNM
|
46
|
+
# Runner class handles running a scenario through RNM-US and retrieving results
|
47
|
+
class Runner
|
48
|
+
##
|
49
|
+
# Initialize Runner attributes: +name+ , +root directory+ , +run directory+ and +feature_file_path+
|
50
|
+
##
|
51
|
+
# [parameters:]
|
52
|
+
# * +name+ - _String_ - Human readable scenario name.
|
53
|
+
# * +run_dir+ - _String_ - Full path to directory for simulation of this scenario
|
54
|
+
# * +feature_file_path+ - _String_ - Full path to GeoJSON feature file containing features and streets for simulation.
|
55
|
+
# * +scenario_csv_path+ - _String_ - Full path to the Scenario CSV file containing list of features to run for this scenario.
|
56
|
+
# * +extended_catalog_path+ - _String_ - Full path to the extended catalog
|
57
|
+
# * +average_peak_catalog_path+ - _String_ - Full path to average peak catalog
|
58
|
+
# * +reopt+ - _Boolean_ - Use REopt results to generate inputs? Defaults to false
|
59
|
+
# * +opendss_catalog+ - _Boolean_ - Generate OpenDSS catalog? Defaults to true
|
60
|
+
def initialize(name, run_dir, scenario_csv_path, feature_file_path, extended_catalog_path: nil, average_peak_catalog_path: nil, reopt: false, opendss_catalog: true)
|
61
|
+
@name = name
|
62
|
+
# these are all absolute paths
|
63
|
+
@run_dir = run_dir
|
64
|
+
@feature_file_path = feature_file_path
|
65
|
+
@scenario_csv_path = scenario_csv_path
|
66
|
+
@api_client = nil
|
67
|
+
@rnm_dirname = 'rnm-us'
|
68
|
+
@rnm_dir = File.join(@run_dir, @rnm_dirname)
|
69
|
+
@reopt = reopt
|
70
|
+
@extended_catalog_path = extended_catalog_path
|
71
|
+
@average_peak_catalog_path = average_peak_catalog_path
|
72
|
+
@opendss_catalog = opendss_catalog
|
73
|
+
@results = []
|
74
|
+
|
75
|
+
# load feature file
|
76
|
+
@feature_file = JSON.parse(File.read(@feature_file_path))
|
77
|
+
|
78
|
+
# process CSV to get feature IDs only
|
79
|
+
@scenario_features = get_scenario_features
|
80
|
+
|
81
|
+
# set default catalog paths if they are nil
|
82
|
+
if @extended_catalog_path.nil?
|
83
|
+
@extended_catalog_path = File.join(File.dirname(__FILE__), '..', '..', '..', 'catalogs', 'extended_catalog.json')
|
84
|
+
end
|
85
|
+
if @average_peak_catalog_path.nil?
|
86
|
+
@average_peak_catalog_path = File.join(File.dirname(__FILE__), '..', '..', '..', 'catalogs', 'average_peak_per_building_type.json')
|
87
|
+
end
|
88
|
+
|
89
|
+
# initialize @@logger
|
90
|
+
@@logger ||= URBANopt::RNM.logger
|
91
|
+
|
92
|
+
# puts "REOPT: #{@reopt}, OPENDSS_CATALOG: #{@opendss_catalog}"
|
93
|
+
end
|
94
|
+
|
95
|
+
##
|
96
|
+
# Name of the Scenario.
|
97
|
+
attr_reader :name #:nodoc:
|
98
|
+
|
99
|
+
##
|
100
|
+
# Directory to run this Scenario.
|
101
|
+
attr_reader :run_dir #:nodoc:
|
102
|
+
|
103
|
+
##
|
104
|
+
# Feature file path associated with this Scenario.
|
105
|
+
attr_reader :feature_file_path #:nodoc:
|
106
|
+
|
107
|
+
##
|
108
|
+
# Scenario CSV path associated with this Scenario.
|
109
|
+
attr_reader :scenario_csv_path #:nodoc:
|
110
|
+
|
111
|
+
##
|
112
|
+
# Feature file path associated with this Scenario.
|
113
|
+
attr_reader :reopt #:nodoc:
|
114
|
+
|
115
|
+
##
|
116
|
+
# Feature file path associated with this Scenario.
|
117
|
+
attr_reader :average_peak_catalog_path #:nodoc:
|
118
|
+
|
119
|
+
##
|
120
|
+
# Feature file path associated with this Scenario.
|
121
|
+
attr_reader :extended_catalog_path #:nodoc:
|
122
|
+
|
123
|
+
##
|
124
|
+
# Get Scenario Features
|
125
|
+
##
|
126
|
+
def get_scenario_features
|
127
|
+
@num_header_rows = 1
|
128
|
+
features = []
|
129
|
+
CSV.foreach(@scenario_csv_path, :headers => true) do |row|
|
130
|
+
|
131
|
+
break if row[0].nil?
|
132
|
+
|
133
|
+
# gets +feature_id+ and append to list
|
134
|
+
features << row[0].chomp
|
135
|
+
end
|
136
|
+
return features
|
137
|
+
end
|
138
|
+
|
139
|
+
##
|
140
|
+
# Create RNM-US Input Files
|
141
|
+
##
|
142
|
+
def create_simulation_files
|
143
|
+
# generate RNM-US input files
|
144
|
+
in_files = URBANopt::RNM::InputFiles.new(@run_dir, @scenario_features, @feature_file, @extended_catalog_path, @average_peak_catalog_path, reopt: @reopt, opendss_catalog: @opendss_catalog)
|
145
|
+
in_files.create
|
146
|
+
end
|
147
|
+
|
148
|
+
##
|
149
|
+
# Run RNM-US Simulation (via RNM-US api) and get results
|
150
|
+
##
|
151
|
+
# [parameters:]
|
152
|
+
# * +use_local+ - _Boolean_ - Flag to use localhost API vs production API
|
153
|
+
def run(use_local = false)
|
154
|
+
# start client
|
155
|
+
@api_client = URBANopt::RNM::ApiClient.new(@name, @rnm_dir, use_localhost = use_local, reopt = @reopt)
|
156
|
+
@api_client.zip_input_files
|
157
|
+
@api_client.submit_simulation
|
158
|
+
@results = @api_client.get_results
|
159
|
+
end
|
160
|
+
|
161
|
+
##
|
162
|
+
# Download results for a simulation separately
|
163
|
+
##
|
164
|
+
def download_results(sim_id = nil)
|
165
|
+
@api_client.download_results(sim_id)
|
166
|
+
end
|
167
|
+
|
168
|
+
##
|
169
|
+
# Post-process results back into scenario json file
|
170
|
+
##
|
171
|
+
def post_process
|
172
|
+
@rnm_pp = URBANopt::RNM::PostProcessor.new(@results, @run_dir, @feature_file)
|
173
|
+
@rnm_pp.post_process
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
# *********************************************************************************
|
2
|
+
# URBANopt (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
|
3
|
+
# contributors. All rights reserved.
|
4
|
+
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
# are permitted provided that the following conditions are met:
|
7
|
+
|
8
|
+
# Redistributions of source code must retain the above copyright notice, this list
|
9
|
+
# of conditions and the following disclaimer.
|
10
|
+
|
11
|
+
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
|
+
# list of conditions and the following disclaimer in the documentation and/or other
|
13
|
+
# materials provided with the distribution.
|
14
|
+
|
15
|
+
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
|
+
# used to endorse or promote products derived from this software without specific
|
17
|
+
# prior written permission.
|
18
|
+
|
19
|
+
# Redistribution of this software, without modification, must refer to the software
|
20
|
+
# by the same designation. Redistribution of a modified version of this software
|
21
|
+
# (i) may not refer to the modified version by the same designation, or by any
|
22
|
+
# confusingly similar designation, and (ii) must refer to the underlying software
|
23
|
+
# originally provided by Alliance as "URBANopt". Except to comply with the foregoing,
|
24
|
+
# the term "URBANopt", or any confusingly similar designation may not be used to
|
25
|
+
# refer to any modified version of this software or any modified version of the
|
26
|
+
# underlying software originally provided by Alliance without the prior written
|
27
|
+
# consent of Alliance.
|
28
|
+
|
29
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
30
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
31
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
32
|
+
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
33
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
34
|
+
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
35
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
36
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
37
|
+
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
38
|
+
# OF THE POSSIBILITY OF SUCH DAMAGE.
|
39
|
+
# *********************************************************************************
|
40
|
+
|
41
|
+
module URBANopt
|
42
|
+
module RNM
|
43
|
+
class ReportScenario
|
44
|
+
attr_accessor :hour_index_max_res, :hour_index_min_res, :peak_hour_max_res, :peak_hour_min_res, :hour_index_max_comm, :hour_index_min_comm, :peak_hour_max_comm, :peak_hour_min_comm
|
45
|
+
|
46
|
+
def initialize(reopt)
|
47
|
+
@reopt = reopt
|
48
|
+
@hour_index_max_res = hour_index_max_res
|
49
|
+
@hour_index_min_res = hour_index_min_res
|
50
|
+
@peak_hour_max_res = peak_hour_max_res
|
51
|
+
@peak_hour_min_res = peak_hour_min_res
|
52
|
+
@hour_index_max_comm = hour_index_max_comm
|
53
|
+
@hour_index_min_comm = hour_index_min_comm
|
54
|
+
@peak_hour_max_comm = peak_hour_max_comm
|
55
|
+
@peak_hour_min_comm = peak_hour_min_comm
|
56
|
+
@res_consumption = []
|
57
|
+
@commercial_consumption = []
|
58
|
+
@time = []
|
59
|
+
end
|
60
|
+
|
61
|
+
# creating a method passing the GEOjson file from URBANopt as the argument to define streets and building (customers) coordinates
|
62
|
+
# and returning the street coordinates array, the building coordinates array and the tot number of buildings in the project
|
63
|
+
|
64
|
+
def scenario_report_results
|
65
|
+
max_net_load_res = 0
|
66
|
+
max_net_load_comm = 0
|
67
|
+
min_net_load_res = 500000
|
68
|
+
min_net_load_comm = 500000
|
69
|
+
# j = 0
|
70
|
+
# insert scenario path
|
71
|
+
# if include reopt getting 2 most-stressing days in the year (max net load & min net load)
|
72
|
+
if @reopt
|
73
|
+
(0..@commercial_consumption.length - 1).each do |j|
|
74
|
+
if @commercial_consumption[j] > max_net_load_comm
|
75
|
+
max_net_load_comm = @commercial_consumption[j]
|
76
|
+
@peak_hour_max_comm = (@time[j].split(' ')[1]).split(':')[0].to_i # defined the most-stressing scenario
|
77
|
+
@hour_index_max_comm = j
|
78
|
+
end
|
79
|
+
if @commercial_consumption[j] < min_net_load_comm
|
80
|
+
min_net_load_comm = @commercial_consumption[j]
|
81
|
+
@peak_hour_min_comm = (@time[j].split(' ')[1]).split(':')[0].to_i # defined the most-stressing scenario
|
82
|
+
@hour_index_min_comm = j
|
83
|
+
end
|
84
|
+
|
85
|
+
if @res_consumption[j] > max_net_load_res
|
86
|
+
max_net_load_res = @res_consumption[j]
|
87
|
+
@peak_hour_max_res = (@time[j].split(' ')[1]).split(':')[0].to_i # defined the most-stressing scenario
|
88
|
+
@hour_index_max_res = j
|
89
|
+
end
|
90
|
+
if @res_consumption[j] < min_net_load_res
|
91
|
+
min_net_load_res = @res_consumption[j]
|
92
|
+
@peak_hour_min_res = (@time[j].split(' ')[1]).split(':')[0].to_i # defined the most-stressing scenario
|
93
|
+
@hour_index_min_res = j
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
else # case when reopt is not run and there is only a consumption scenario, without DG generation
|
98
|
+
(0..@commercial_consumption.length - 1).each do |j|
|
99
|
+
if @commercial_consumption[j] > max_net_load_comm
|
100
|
+
max_net_load_comm = @commercial_consumption[j]
|
101
|
+
@peak_hour_max_comm = (@time[j].split(' ')[1]).split(':')[0].to_i # defined the most-stressing scenario
|
102
|
+
@hour_index_max_comm = j
|
103
|
+
end
|
104
|
+
if @res_consumption[j] > max_net_load_res
|
105
|
+
max_net_load_res = @res_consumption[j]
|
106
|
+
@peak_hour_max_res = (@time[j].split(' ')[1]).split(':')[0].to_i # defined the most-stressing scenario
|
107
|
+
@hour_index_max_res = j
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
def aggregate_consumption(file_csv, file_json, n_feature)
|
113
|
+
feature_type = file_json['program']['building_types'][0]['building_type']
|
114
|
+
# residential_building_types = "Single-Family Detached" #add the other types
|
115
|
+
residential_building_types = ['Single-Family Detached', 'Single-Family Attached', 'MultiFamily', 'Single-Family', 'Multifamily Detached (2 to 4 units)', 'Multifamily Detached (5 or more units)'] # add the other types
|
116
|
+
puts feature_type
|
117
|
+
j = 0
|
118
|
+
CSV.foreach(file_csv, headers: true) do |power|
|
119
|
+
@time[j] = power['Datetime']
|
120
|
+
if n_feature == 0
|
121
|
+
@res_consumption[j] = 0
|
122
|
+
@commercial_consumption[j] = 0
|
123
|
+
end
|
124
|
+
if @reopt
|
125
|
+
if residential_building_types.include? feature_type
|
126
|
+
@res_consumption[j] += power['REopt:Electricity:Load:Total(kw)'].to_i + power['REopt:Electricity:Grid:ToBattery(kw)'].to_i + power['REopt:ElectricityProduced:PV:ToBattery(kw)'].to_i + power['REopt:ElectricityProduced:Wind:ToBattery(kw)'].to_i + power['REopt:ElectricityProduced:Generator:ToBattery(kw)'].to_i - power['REopt:Electricity:Storage:ToLoad(kw)'].to_i - power['REopt:Electricity:Storage:ToGrid(kw)'].to_i - power['REopt:ElectricityProduced:Total(kw)'].to_i
|
127
|
+
j += 1
|
128
|
+
else
|
129
|
+
@commercial_consumption[j] += power['REopt:Electricity:Load:Total(kw)'].to_i + power['REopt:Electricity:Grid:ToBattery(kw)'].to_i + power['REopt:ElectricityProduced:PV:ToBattery(kw)'].to_i + power['REopt:ElectricityProduced:Wind:ToBattery(kw)'].to_i + power['REopt:ElectricityProduced:Generator:ToBattery(kw)'].to_i - power['REopt:Electricity:Storage:ToLoad(kw)'].to_i - power['REopt:Electricity:Storage:ToGrid(kw)'].to_i - power['REopt:ElectricityProduced:Total(kw)'].to_i
|
130
|
+
j += 1
|
131
|
+
end
|
132
|
+
else
|
133
|
+
if residential_building_types.include? feature_type
|
134
|
+
@res_consumption[j] += power['Electricity:Facility Power(kW)'].to_i
|
135
|
+
j += 1
|
136
|
+
else
|
137
|
+
@commercial_consumption[j] += power['Electricity:Facility Power(kW)'].to_i
|
138
|
+
j += 1
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# *********************************************************************************
|
2
|
+
# URBANopt (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
|
3
|
+
# contributors. All rights reserved.
|
4
|
+
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
# are permitted provided that the following conditions are met:
|
7
|
+
|
8
|
+
# Redistributions of source code must retain the above copyright notice, this list
|
9
|
+
# of conditions and the following disclaimer.
|
10
|
+
|
11
|
+
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
|
+
# list of conditions and the following disclaimer in the documentation and/or other
|
13
|
+
# materials provided with the distribution.
|
14
|
+
|
15
|
+
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
|
+
# used to endorse or promote products derived from this software without specific
|
17
|
+
# prior written permission.
|
18
|
+
|
19
|
+
# Redistribution of this software, without modification, must refer to the software
|
20
|
+
# by the same designation. Redistribution of a modified version of this software
|
21
|
+
# (i) may not refer to the modified version by the same designation, or by any
|
22
|
+
# confusingly similar designation, and (ii) must refer to the underlying software
|
23
|
+
# originally provided by Alliance as "URBANopt". Except to comply with the foregoing,
|
24
|
+
# the term "URBANopt", or any confusingly similar designation may not be used to
|
25
|
+
# refer to any modified version of this software or any modified version of the
|
26
|
+
# underlying software originally provided by Alliance without the prior written
|
27
|
+
# consent of Alliance.
|
28
|
+
|
29
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
30
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
31
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
32
|
+
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
33
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
34
|
+
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
35
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
36
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
37
|
+
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
38
|
+
# OF THE POSSIBILITY OF SUCH DAMAGE.
|
39
|
+
# *********************************************************************************
|
40
|
+
|
41
|
+
# version for integrating DG, UG-OH in RNM-US
|
42
|
+
require 'geoutm'
|
43
|
+
require 'json'
|
44
|
+
module URBANopt
|
45
|
+
module RNM
|
46
|
+
class PrimarySubstation
|
47
|
+
# attr_accessor :x, :y, :id
|
48
|
+
# choose the closest coord to the street or the one in the midle of the polygon since the sub is far away from district and streets
|
49
|
+
def coordinates(points_coord, id)
|
50
|
+
x_utm = []
|
51
|
+
y_utm = []
|
52
|
+
for i in 0..points_coord.length - 1
|
53
|
+
lat_lon = GeoUtm::LatLon.new(points_coord[i][1], points_coord[i][0])
|
54
|
+
utm = lat_lon.to_utm # converting latitude and longitude to UTM
|
55
|
+
x_utm[i] = utm.e.round(2) # UTM x-distance from the origin
|
56
|
+
y_utm[i] = utm.n.round(2) # UTM y-distance from the origin
|
57
|
+
end
|
58
|
+
coord_sub = [(x_utm[0] + x_utm[2]) / 2, (y_utm[0] + y_utm[2]) / 2, 0, "sub_#{id}"]
|
59
|
+
return coord_sub
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# *********************************************************************************
|
2
|
+
# URBANopt (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
|
3
|
+
# contributors. All rights reserved.
|
4
|
+
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
# are permitted provided that the following conditions are met:
|
7
|
+
|
8
|
+
# Redistributions of source code must retain the above copyright notice, this list
|
9
|
+
# of conditions and the following disclaimer.
|
10
|
+
|
11
|
+
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
|
+
# list of conditions and the following disclaimer in the documentation and/or other
|
13
|
+
# materials provided with the distribution.
|
14
|
+
|
15
|
+
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
|
+
# used to endorse or promote products derived from this software without specific
|
17
|
+
# prior written permission.
|
18
|
+
|
19
|
+
# Redistribution of this software, without modification, must refer to the software
|
20
|
+
# by the same designation. Redistribution of a modified version of this software
|
21
|
+
# (i) may not refer to the modified version by the same designation, or by any
|
22
|
+
# confusingly similar designation, and (ii) must refer to the underlying software
|
23
|
+
# originally provided by Alliance as "URBANopt". Except to comply with the foregoing,
|
24
|
+
# the term "URBANopt", or any confusingly similar designation may not be used to
|
25
|
+
# refer to any modified version of this software or any modified version of the
|
26
|
+
# underlying software originally provided by Alliance without the prior written
|
27
|
+
# consent of Alliance.
|
28
|
+
|
29
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
30
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
31
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
32
|
+
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
33
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
34
|
+
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
35
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
36
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
37
|
+
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
38
|
+
# OF THE POSSIBILITY OF SUCH DAMAGE.
|
39
|
+
# *********************************************************************************
|
40
|
+
module URBANopt
|
41
|
+
module RNM
|
42
|
+
# creating the Transformers class with required parameters by the OpenDSS catalog
|
43
|
+
class Transformers
|
44
|
+
def create(trafo)
|
45
|
+
hash = {}
|
46
|
+
hash[:nameclass] = trafo['Name']
|
47
|
+
if trafo.include? 'Installed Power(MVA)'
|
48
|
+
hash[:kva] = (trafo['Installed Power(MVA)'].to_i * 1000).to_i # converting to kVA
|
49
|
+
else # trafo.include? "kVA"
|
50
|
+
hash[:kva] = trafo['Installed Power(kVA)']
|
51
|
+
end
|
52
|
+
hash[:resistance] = trafo['Low-voltage-side short-circuit resistance (ohms)'].to_f.round(2)
|
53
|
+
hash[:reactance] = trafo['Reactance (p.u. transf)'].to_f.round(2)
|
54
|
+
hash[:phases] = trafo['Nphases']
|
55
|
+
if trafo['Nphases'] == '3'
|
56
|
+
hash[:is_center_tap] = false
|
57
|
+
else
|
58
|
+
hash[:is_center_tap] = true
|
59
|
+
end
|
60
|
+
hash[:high_voltage] = trafo['Primary Voltage (kV)']
|
61
|
+
hash[:low_voltage] = trafo['Secondary Voltage (kV)']
|
62
|
+
hash[:connection] = trafo['connection']
|
63
|
+
return hash
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|