This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Controlled_Voltage_Source: | |
""" Controlled Voltage Source class. Takes the instantaneous | |
voltage as input from the user file. """ | |
def __init__(self, volt_index, volt_pos, volt_tag): | |
""" Constructor to initialize value. | |
Also, takes in the identifiers - | |
index (serial number), cell position and tag. """ | |
self.type="ControlledVoltageSource" | |
self.volt_number=volt_index | |
self.volt_pos=volt_pos | |
self.pos=volt_pos | |
self.volt_tag=volt_tag | |
self.tag=volt_tag | |
self.voltage=0.0 | |
self.current=0.0 | |
self.op_value=0.0 | |
self.v_polrty=[-1, -1] | |
self.control_tag=["Control"] | |
self.control_values=[0.0] | |
def display(self): | |
""" Displays info about the component.""" | |
print "Controlled Voltage Source is ", | |
print self.volt_tag, | |
print " located at ", | |
print self.volt_pos, | |
print " with positive polarity towards %s" %(csv_element(self.v_polrty)) | |
def ask_values(self, x_list, ckt_mat, sys_branch): | |
""" Writes the values needed to the spreadsheet.""" | |
volt_params=["ControlledVoltageSource"] | |
volt_params.append(self.volt_tag) | |
volt_params.append(self.volt_pos) | |
if self.v_polrty==[-1, -1]: | |
# Looking for a default value of polarity | |
# in the neighbouring cells | |
self.volt_elem=csv_tuple(self.volt_pos) | |
if self.volt_elem[0]>0: | |
if ckt_mat[self.volt_elem[0]-1][self.volt_elem[1]]: | |
self.v_polrty=[self.volt_elem[0]-1, self.volt_elem[1]] | |
if self.volt_elem[1]>0: | |
if ckt_mat[self.volt_elem[0]][self.volt_elem[1]-1]: | |
self.v_polrty=[self.volt_elem[0], self.volt_elem[1]-1] | |
if self.volt_elem[0]<len(ckt_mat)-1: | |
if ckt_mat[self.volt_elem[0]+1][self.volt_elem[1]]: | |
self.v_polrty=[self.volt_elem[0]+1, self.volt_elem[1]] | |
if self.volt_elem[1]<len(ckt_mat)-1: | |
if ckt_mat[self.volt_elem[0]][self.volt_elem[1]+1]: | |
self.v_polrty=[self.volt_elem[0], self.volt_elem[1]+1] | |
else: | |
for c1 in range(len(sys_branch)): | |
if csv_tuple(self.volt_pos) in sys_branch[c1]: | |
if not self.v_polrty in sys_branch[c1]: | |
print "!"*50 | |
print "ERROR!!! Voltage source polarity should be in the same branch as the voltage source. Check source at %s" %self.volt_pos | |
print "!"*50 | |
volt_params.append("Positive polarity towards (cell) = %s" %csv_element(self.v_polrty)) | |
volt_params.append("Name of control signal = %s" %self.control_tag[0]) | |
x_list.append(volt_params) | |
def get_values(self, x_list, ckt_mat): | |
""" Takes the parameter from the spreadsheet.""" | |
volt_polrty=x_list[0].split("=")[1] | |
# Convert the human readable form of cell | |
# to [row, column] form | |
while volt_polrty[0]==" ": | |
volt_polrty=volt_polrty[1:] | |
self.v_polrty=csv_tuple(volt_polrty) | |
if not ckt_mat[self.v_polrty[0]][self.v_polrty[1]]: | |
print "Polarity incorrect. Branch does not exist at %s" %csv_element(self.v_polrty) | |
self.control_tag[0]=x_list[1].split("=")[1] | |
while self.control_tag[0][0]==" ": | |
self.control_tag[0]=self.control_tag[0][1:] | |
return | |
def transfer_to_sys(self, sys_loops, mat_e, mat_a, mat_b, mat_u, source_list): | |
""" The matrix B in E.dx/dt=Ax+Bu will be updated by the | |
polarity of the voltage source.""" | |
for c1 in range(len(sys_loops)): | |
for c2 in range(len(sys_loops[c1][c1])): | |
if csv_tuple(self.volt_pos) in sys_loops[c1][c1][c2]: | |
# If the positive polarity appears before the voltage position | |
# it means as per KVL, we are moving from +ve to -ve | |
# and so the voltage will be taken negative | |
if sys_loops[c1][c1][c2].index(self.v_polrty)<sys_loops[c1][c1][c2].index(csv_tuple(self.volt_pos)): | |
if sys_loops[c1][c1][c2][-1]=="forward": | |
mat_b.data[c1][source_list.index(self.volt_pos)]=-1.0 | |
else: | |
mat_b.data[c1][source_list.index(self.volt_pos)]=1.0 | |
else: | |
if sys_loops[c1][c1][c2][-1]=="forward": | |
mat_b.data[c1][source_list.index(self.volt_pos)]=1.0 | |
else: | |
mat_b.data[c1][source_list.index(self.volt_pos)]=-1.0 | |
return | |
def transfer_to_branch(self, sys_branch, source_list): | |
""" Transfers parameters to system branch if voltage | |
source exists in the branch. """ | |
if csv_tuple(self.volt_pos) in sys_branch: | |
if sys_branch.index(self.v_polrty)<sys_branch.index(csv_tuple(self.volt_pos)): | |
sys_branch[-1][1][source_list.index(self.volt_pos)]=-1.0 | |
else: | |
sys_branch[-1][1][source_list.index(self.volt_pos)]=1.0 | |
def generate_val(self, source_lst, sys_loops, mat_e, mat_a, mat_b, mat_u, t, dt): | |
""" The source voltage is updated in the matrix u in | |
E.dx/dt=Ax+Bu .""" | |
mat_u.data[source_lst.index(self.volt_pos)][0]=self.control_values[0] | |
self.op_value=self.control_values[0] | |
def update_val(self, sys_loops, lbyr_ratio, mat_e, mat_a, mat_b, state_vec, mat_u): | |
pass |
Next in the main program "circuit_solver.py". The first stage is to get the names of the control codes from the user. Then generate "descriptor" files for each of these control codes. Check if they exist. If they don't create blank templates (check the previous blog entry). This is the code (click on "view raw" below the code box to see it in a new window):
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This is the main control program | |
# It will contain the individual control | |
# codes as functions. | |
complete_control=open("__control.py","w") | |
# Check if there exists a controlled element | |
if controlled_elements: | |
user_input=raw_input("Enter the control files. Omit the .py extension and just leave spaces between files --> ") | |
control_files=user_input.split() | |
control_descs=[] | |
for c1 in range(len(control_files)): | |
control_descs.append(control_files[c1]+"_desc.csv") | |
control_functions=[] | |
for c1 in range(len(control_files)): | |
control_functions.append(control_files[c1]+"_func") | |
for c1 in range(len(control_files)): | |
control_files[c1]=control_files[c1]+".py" | |
# These lists will contain separate dictionaries | |
# for every control file. | |
control_file_inputs=[] | |
control_file_outputs=[] | |
control_file_staticvars=[] | |
control_file_timeevents=[] | |
control_desc_handles=[] | |
for c1 in range(len(control_files)): | |
# Adding an empty dictionary for a control file. | |
control_file_inputs.append({}) | |
control_file_outputs.append({}) | |
control_file_staticvars.append({}) | |
control_file_timeevents.append({}) | |
# Check if the descriptor exists. | |
try: | |
control_desc_handles.append(open(control_descs[c1],"r")) | |
except: | |
# If it doesn't create a blank template. | |
control_desc_handles.append(open(control_descs[c1],"w")) | |
# Input template | |
control_desc_handles[c1].write("Input") | |
control_desc_handles[c1].write(", ") | |
control_desc_handles[c1].write("Element name in circuit spreadsheet = %s" %(component_objects[meter_list[0]].type+"_"+component_objects[meter_list[0]].tag)) | |
control_desc_handles[c1].write(", ") | |
control_desc_handles[c1].write("Desired variable name in control code = %s" %(component_objects[meter_list[0]].type+"_"+component_objects[meter_list[0]].tag)) | |
control_desc_handles[c1].write(", ") | |
control_desc_handles[c1].write("\n") | |
# Output template. Create a line for every | |
# control input a particular controlled | |
# element has. | |
for c2 in range(len(component_objects[controlled_elements[0]].control_tag)): | |
control_desc_handles[c1].write("Output") | |
control_desc_handles[c1].write(", ") | |
control_desc_handles[c1].write("Element name in circuit spreadsheet = %s" %(component_objects[controlled_elements[0]].type+"_"+component_objects[controlled_elements[0]].tag)) | |
control_desc_handles[c1].write(", ") | |
control_desc_handles[c1].write("Control tag defined in parameters spreadhseet = %s" %(component_objects[controlled_elements[0]].control_tag[c2])) | |
control_desc_handles[c1].write(", ") | |
control_desc_handles[c1].write("Desired variable name in control code = %s" %(component_objects[controlled_elements[0]].control_tag[c2])) | |
control_desc_handles[c1].write(", ") | |
control_desc_handles[c1].write("\n") | |
# Static variable template | |
control_desc_handles[c1].write("StaticVariable") | |
control_desc_handles[c1].write(", ") | |
control_desc_handles[c1].write("Desired variable name in control code = Var1") | |
control_desc_handles[c1].write(", ") | |
control_desc_handles[c1].write("Initial value of variable = 0.0") | |
control_desc_handles[c1].write(", ") | |
control_desc_handles[c1].write("\n") | |
# Time event template | |
control_desc_handles[c1].write("TimeEvent") | |
control_desc_handles[c1].write(", ") | |
control_desc_handles[c1].write("Desired variable name in control code = t1") | |
control_desc_handles[c1].write(", ") | |
control_desc_handles[c1].write("First time event = 0.0") | |
control_desc_handles[c1].write(", ") | |
control_desc_handles[c1].write("\n") | |
control_desc_handles[c1].close() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Wait for the user to enter parameters before | |
# reading the *_desc.csv file. | |
cont_ans="n" | |
while cont_ans.lower()!="y": | |
print "Enter control parameters in the following files --> " | |
for c1 in range(len(control_descs)): | |
print "%s " %control_descs[c1] | |
cont_ans=raw_input("When ready press y and enter to continue -> ") | |
# Read the parameters from the descriptor spreadsheet. | |
control_desc_handles=[] | |
for c1 in range(len(control_files)): | |
control_desc_handles.append(open(control_descs[c1],"r")) | |
params_from_file=reading_params(control_desc_handles[c1]) | |
for c2 in range(len(params_from_file)): | |
# Scrubbing blank spaces from the beginning | |
# and the end of the first cell. | |
while params_from_file[c2][0][0]==" ": | |
params_from_file[c2][0]=params_from_file[c2][0][1:] | |
while params_from_file[c2][0][-1]==" ": | |
params_from_file[c2][0]=params_from_file[c2][0][:-1] | |
if params_from_file[c2][0].lower()=="input": | |
# If it is an input, it will be a meter. | |
meter_type=params_from_file[c2][1].split("=")[1] | |
while meter_type[0]==" ": | |
meter_type=meter_type[1:] | |
while meter_type[-1]==" ": | |
meter_type=meter_type[:-1] | |
# Look for the meter in components_found | |
# and get the cell position from the meter tag. | |
# The cell position which is unique will be the | |
# dictionary key for control_file_inputs. | |
for c3 in range(len(components_found[meter_type.split("_")[0].lower()])): | |
if components_found[meter_type.split("_")[0].lower()][c3][1]==meter_type.split("_")[1]: | |
meter_type_ref=meter_type.split("_")[0].lower() | |
control_file_inputs[c1][components_found[meter_type_ref][c3][0]]=[components_found[meter_type_ref][c3][1]] | |
var_name=params_from_file[c2][2].split("=")[1] | |
while var_name[0]==" ": | |
var_name=var_name[1:] | |
while var_name[-1]==" ": | |
var_name=var_name[:-1] | |
control_file_inputs[c1][components_found[meter_type_ref][c3][0]].append(var_name) | |
if params_from_file[c2][0].lower()=="output": | |
# If it is an output, it is a controlled element | |
element_type=params_from_file[c2][1].split("=")[1] | |
while element_type[0]==" ": | |
element_type=element_type[1:] | |
while element_type[-1]==" ": | |
element_type=element_type[:-1] | |
# Look for the controlled element in components_found | |
# and get the cell position from the device tag. | |
# The cell position will be the unique dictionary key | |
for c3 in range(len(components_found[element_type.split("_")[0].lower()])): | |
if components_found[element_type.split("_")[0].lower()][c3][1]==element_type.split("_")[1]: | |
element_type_ref=element_type.split("_")[0].lower() | |
# Since a controlled element can have more than one control input | |
# Check if it has been found before. | |
if not components_found[element_type_ref][c3][0] in control_file_outputs[c1].keys(): | |
control_file_outputs[c1][components_found[element_type_ref][c3][0]]=[components_found[element_type_ref][c3][1]] | |
control_tag_name=params_from_file[c2][2].split("=")[1] | |
control_var_name=params_from_file[c2][3].split("=")[1] | |
while control_tag_name[0]==" ": | |
control_tag_name=control_tag_name[1:] | |
while control_tag_name[-1]==" ": | |
control_tag_name=control_tag_name[:-1] | |
while control_var_name[0]==" ": | |
control_var_name=control_var_name[1:] | |
while control_var_name[-1]==" ": | |
control_var_name=control_var_name[:-1] | |
control_file_outputs[c1][components_found[element_type_ref][c3][0]].append([control_tag_name, control_var_name, 0.0]) | |
if params_from_file[c2][0].lower()=="staticvariable": | |
# If it is a staticvariable, the dictionary key | |
# will be the variable name. | |
staticvar_type=params_from_file[c2][1].split("=")[1] | |
while staticvar_type[0]==" ": | |
staticvar_type=staticvar_type[1:] | |
while staticvar_type[-1]==" ": | |
staticvar_type=staticvar_type[:-1] | |
staticvar_val=params_from_file[c2][2].split("=")[1] | |
while staticvar_val[0]==" ": | |
staticvar_val=staticvar_val[1:] | |
while staticvar_val[-1]==" ": | |
staticvar_val=staticvar_val[:-1] | |
control_file_staticvars[c1][staticvar_type]=float(staticvar_val) | |
if params_from_file[c2][0].lower()=="timeevent": | |
# If it is a timeevent, the dictionary key | |
# will be the variable name. | |
timeevent_type=params_from_file[c2][1].split("=")[1] | |
while timeevent_type[0]==" ": | |
timeevent_type=timeevent_type[1:] | |
while timeevent_type[-1]==" ": | |
timeevent_type=timeevent_type[:-1] | |
timeevent_val=params_from_file[c2][2].split("=")[1] | |
while timeevent_val[0]==" ": | |
timeevent_val=timeevent_val[1:] | |
while timeevent_val[-1]==" ": | |
timeevent_val=timeevent_val[:-1] | |
control_file_timeevents[c1][timeevent_type]=float(timeevent_val) | |
control_desc_handles[c1].close() |
So basically, define the function, assign the input to variables, assign the static variables to local variables, assign the time events to local variables. And then finally embed the control code. Then assign the local variables to outputs, reassign local variables to static variables and time events as applicable to take these back to the main program.
Here is the code (click on "view raw" below the code box to see it in a new window):
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Wait for use to update the control code. | |
cont_ans="n" | |
while cont_ans.lower()!="y": | |
print "Enter control code in the following files --> " | |
for c1 in range(len(control_files)): | |
print "%s " %control_files[c1] | |
cont_ans=raw_input("When ready press y and enter to continue -> ") | |
# This list will contain the control | |
# code as lists of strings. | |
control_code=[] | |
for c1 in range(len(control_files)): | |
control_code.append([]) | |
control_handles=[] | |
for c1 in range(len(control_files)): | |
control_handles.append(open(control_files[c1],"r")) | |
# Add the lines in the control codes | |
# to the lists. | |
for line in control_handles[c1]: | |
control_code[c1].append(line) | |
control_handles[c1].close() | |
# Check for any import statements. | |
# If any of the control codes have import statements | |
# add them to the main control program. | |
for c1 in range(len(control_code)): | |
for c2 in range(len(control_code[c1])): | |
if "import" in control_code[c1][c2].split(): | |
complete_control.write(control_code[c1][c2]) | |
complete_control.write("\n") | |
for c1 in range(len(control_code)): | |
# For each control code, define a function | |
# Name of function has been defined in | |
# control_functions. | |
complete_control.write("def %s(interface_inputs, interface_outputs, interface_static, interface_time, circuit_components, pos, t_clock):" %control_functions[c1]) | |
complete_control.write("\n") | |
# The remaining statements have a tab \t for indentation | |
# Assign the input variables to the meter outputs | |
for ip_keys in control_file_inputs[c1].keys(): | |
complete_control.write("\t") | |
complete_control.write("%s=circuit_components['%s'].op_value" %(control_file_inputs[c1][ip_keys][1], ip_keys)) | |
complete_control.write("\n") | |
# Assign the static variables to their latest values | |
for static_keys in control_file_staticvars[c1].keys(): | |
complete_control.write("\t") | |
complete_control.write("%s=interface_static[pos]['%s']" %(static_keys, static_keys)) | |
complete_control.write("\n") | |
# Assign the time events variables to their latest values | |
for time_keys in control_file_timeevents[c1].keys(): | |
complete_control.write("\t") | |
complete_control.write("%s=interface_time[pos]['%s']" %(time_keys, time_keys)) | |
complete_control.write("\n") | |
# Include the control code. | |
for c2 in range(len(control_code[c1])): | |
complete_control.write("\t") | |
complete_control.write(control_code[c1][c2]) | |
# Assign the output controlled elements to the | |
# variables. Additionally, check each control element | |
# for multiple control inputs. | |
for op_keys in control_file_outputs[c1].keys(): | |
for c3 in range(1, len(control_file_outputs[c1][op_keys])): | |
control_pos=component_objects[op_keys].control_tag.index(control_file_outputs[c1][op_keys][c3][0]) | |
complete_control.write("\t") | |
# Update the object control values | |
complete_control.write("circuit_components['%s'].control_values[%d]=%s" %(op_keys, control_pos, control_file_outputs[c1][op_keys][c3][1])) | |
complete_control.write("\n") | |
complete_control.write("\t") | |
# Update the dictionary values | |
complete_control.write("interface_outputs[pos]['%s'][%d][2]=%s" %(op_keys, c3, control_file_outputs[c1][op_keys][c3][1])) | |
complete_control.write("\n") | |
# Store the static variables in the dictionary | |
for static_keys in control_file_staticvars[c1].keys(): | |
complete_control.write("\t") | |
complete_control.write("interface_static[pos]['%s']=%s" %(static_keys, static_keys)) | |
complete_control.write("\n") | |
# Store the time events in the dictionary | |
for time_keys in control_file_timeevents[c1].keys(): | |
complete_control.write("\t") | |
complete_control.write("interface_time[pos]['%s']=%s" %(time_keys, time_keys)) | |
complete_control.write("\n") | |
# end the function | |
complete_control.write("\t") | |
complete_control.write("return") | |
complete_control.write("\n") | |
complete_control.write("\n") | |
complete_control.close() | |
# Import the main control program | |
from __control import * |
No comments:
Post a Comment