11
22import opendssdirect as dss
33import os , math
4+ import pandas as pd
45
56from global_aux import OpenDSS_message_types , input_datasets , non_pev_feeder_load
67
78
89class open_dss :
910
11+ # NOTE: The 'open_dss' class does two things: Use OpenDSS, and do logging.
12+ # if the boolean 'use_opendss' is false, then this class will just do the logging.
13+ # TODO: Separate the logging into a separate federate.
14+ def __init__ (self , base_dir , use_opendss ):
15+
16+ if use_opendss == True :
17+ self .helper = open_dss_helper (base_dir )
18+ else :
19+ self .helper = logger_helper (base_dir )
20+
21+
22+ def get_input_dataset_enum_list (self ):
23+ return self .helper .get_request_list ()
24+
25+
26+ def load_input_datasets (self , datasets_dict ):
27+ self .helper .load_input_datasets (datasets_dict )
28+
29+
30+ def initialize (self ):
31+ return self .helper .initialize ()
32+
33+
34+ def process_control_messages (self , simulation_unix_time , message_dict ):
35+ return self .helper .process_control_messages (simulation_unix_time , message_dict )
36+
37+
38+ def set_caldera_pev_charging_loads (self , node_pevPQ ):
39+ self .helper .set_caldera_pev_charging_loads (node_pevPQ )
40+
41+
42+ def get_pu_node_voltages_for_caldera (self ):
43+ return self .helper .get_pu_node_voltages_for_caldera ()
44+
45+
46+ def solve (self , simulation_unix_time ):
47+ self .helper .solve (simulation_unix_time )
48+
49+
50+ def log_data (self , simulation_unix_time ):
51+ self .helper .log_data (simulation_unix_time )
52+
53+
54+ def post_simulation (self ):
55+ self .helper .post_simulation ()
56+
57+
58+ class open_dss_helper :
59+
1060 def __init__ (self , base_dir ):
1161 self .base_dir = base_dir
1262 self .dss_file_name = 'ieee34.dss'
1363
14-
15- def get_input_dataset_enum_list (self ):
64+ def get_request_list (self ):
1665 return [input_datasets .baseLD_data_obj , input_datasets .all_caldera_node_names , input_datasets .HPSE_caldera_node_names ]
1766
18-
1967 def load_input_datasets (self , datasets_dict ):
2068 # datasets_dict is a dictionary with input_datasets as keys.
2169 self .datasets_dict = datasets_dict
2270
71+ def initialize (self ):
2372
24- def initialize (self ):
2573 baseLD_data_obj = self .datasets_dict [input_datasets .baseLD_data_obj ]
2674 all_caldera_node_names = self .datasets_dict [input_datasets .all_caldera_node_names ]
2775 HPSE_caldera_node_names = self .datasets_dict [input_datasets .HPSE_caldera_node_names ]
@@ -46,29 +94,83 @@ def initialize(self):
4694 self .dss_logger = open_dss_logger_A (self .base_dir , all_caldera_node_names , HPSE_caldera_node_names )
4795
4896 return is_successful
49-
50-
97+
5198 def process_control_messages (self , simulation_unix_time , message_dict ):
5299 return self .dss_external_control .process_control_messages (simulation_unix_time , message_dict )
53100
54-
55101 def set_caldera_pev_charging_loads (self , node_pevPQ ):
56102 self .node_pevPQ = node_pevPQ
57103 self .dss_Caldera .set_caldera_pev_charging_loads (node_pevPQ )
58-
59-
104+
60105 def get_pu_node_voltages_for_caldera (self ):
61106 return self .dss_Caldera .get_pu_node_voltages_for_caldera ()
62-
63-
107+
64108 def solve (self , simulation_unix_time ):
65109 self .dss_core .solve (simulation_unix_time )
66-
67-
110+
68111 def log_data (self , simulation_unix_time ):
69112 self .dss_logger .log_data (simulation_unix_time , self .node_pevPQ )
70113
114+ def post_simulation (self ):
115+ pass
116+
117+ class logger_helper :
118+
119+ def __init__ (self , base_dir ):
120+ self .base_dir = base_dir
121+
122+ def get_request_list (self ):
123+ return [input_datasets .baseLD_data_obj , input_datasets .all_caldera_node_names ]
124+
125+ def load_input_datasets (self , datasets_dict ):
126+ # datasets_dict is a dictionary with input_datasets as keys.
127+ self .datasets_dict = datasets_dict
128+
129+ def initialize (self ):
130+
131+ self .baseLD_data_obj = self .datasets_dict [input_datasets .baseLD_data_obj ]
132+ self .all_caldera_node_names = self .datasets_dict [input_datasets .all_caldera_node_names ]
133+
134+ self .logger_obj = logger (self .base_dir , self .baseLD_data_obj , self .all_caldera_node_names )
135+
136+ is_successful = True
137+ return is_successful
71138
139+ def process_control_messages (self , simulation_unix_time , message_dict ):
140+
141+ return_dict = {}
142+
143+ for (msg_enum , parameters ) in message_dict .items ():
144+ if msg_enum == OpenDSS_message_types .get_all_node_voltages :
145+ return_dict [msg_enum ] = self .get_pu_node_voltages_for_caldera ()
146+
147+ else :
148+ raise ValueError ('Invalid message in caldera_ICM_aux::process_message.' )
149+
150+ # The return value (return_dict) must be a dictionary with OpenDSS_message_types as keys.
151+ # If there is nothing to return, return an empty dictionary.
152+ return return_dict
153+
154+
155+ def set_caldera_pev_charging_loads (self , node_pevPQ ):
156+ self .node_pevPQ = node_pevPQ
157+
158+ def get_pu_node_voltages_for_caldera (self ):
159+ return_dict = {}
160+ for node_name in self .all_caldera_node_names :
161+ return_dict [node_name ] = 1.0
162+
163+ return return_dict
164+
165+ def solve (self , simulation_unix_time ):
166+ self .logger_obj .compute_total_load_profiles (self .node_pevPQ , simulation_unix_time )
167+
168+ def log_data (self , simulation_unix_time ):
169+ return None
170+
171+ def post_simulation (self ):
172+ self .logger_obj .write_data_to_disk ()
173+
72174
73175class open_dss_external_control :
74176
@@ -380,4 +482,63 @@ def log_data(self, simulation_unix_time, node_pevPQ):
380482 node_V = node_V / len (X )
381483
382484 tmp_str = '{}, {}, {}, {}' .format (simulation_time_hrs , node_V , pevQ_kVAR , pevP_kW )
383- f_node .write (tmp_str + '\n ' )
485+ f_node .write (tmp_str + '\n ' )
486+
487+ class logger :
488+
489+ def __init__ (self , base_dir , baseLD_data_obj , all_caldera_node_names ):
490+
491+ self .base_dir = base_dir
492+ self .all_caldera_node_names = all_caldera_node_names
493+ self .baseLD_data_obj = baseLD_data_obj
494+ #print("all_caldera_node_names : {}".format(all_caldera_node_names))
495+
496+ self .real_power_profiles = {}
497+ self .reactive_power_profiles = {}
498+ self .real_power_profiles ["simulation_time_hrs" ] = []
499+ self .real_power_profiles ["base_load_kW" ] = []
500+ self .reactive_power_profiles ["simulation_time_hrs" ] = []
501+ self .reactive_power_profiles ["base_load_kW" ] = []
502+
503+ for node_name in all_caldera_node_names :
504+ self .real_power_profiles [node_name ] = []
505+ self .reactive_power_profiles [node_name ] = []
506+
507+
508+ def compute_total_load_profiles (self , node_pevPQ , simulation_unix_time ):
509+
510+ simulation_time_hrs = simulation_unix_time / 3600.0
511+
512+ index = math .floor ((simulation_unix_time - self .baseLD_data_obj .data_start_unix_time ) / self .baseLD_data_obj .data_timestep_sec )
513+
514+ if (index < 0 ) or (index >= len (self .baseLD_data_obj .actual_load_akW )):
515+ print ("Error : base_LD index computed not in data range" )
516+ exit ()
517+
518+ base_LD_kW = self .baseLD_data_obj .actual_load_akW [index ]
519+ self .real_power_profiles ["simulation_time_hrs" ].append (simulation_time_hrs )
520+ self .real_power_profiles ["base_load_kW" ].append (base_LD_kW )
521+
522+ self .reactive_power_profiles ["simulation_time_hrs" ].append (simulation_time_hrs )
523+ self .reactive_power_profiles ["base_load_kW" ].append (base_LD_kW )
524+
525+ for (node_name , (P_kW , Q_kVAR )) in node_pevPQ .items ():
526+ self .real_power_profiles [node_name ].append (P_kW )
527+ self .reactive_power_profiles [node_name ].append (Q_kVAR )
528+
529+ def write_data_to_disk (self ):
530+ Output_dir = self .base_dir + "/outputs/"
531+
532+ df = pd .DataFrame (self .real_power_profiles )
533+ df .to_csv (Output_dir + "real_power_profiles.csv" , index = False )
534+
535+ df = pd .DataFrame (self .reactive_power_profiles )
536+ df .to_csv (Output_dir + "reactive_power_profiles.csv" , index = False )
537+
538+ def get_pu_node_voltages_for_caldera (self ):
539+
540+ return_dict = {}
541+ for node_name in self .all_caldera_node_names :
542+ return_dict [node_name ] = 1.0
543+
544+ return return_dict
0 commit comments