From 3b12b4a66953ead5cd7c3ae3c8448bd81928b707 Mon Sep 17 00:00:00 2001 From: rkravis Date: Wed, 29 Apr 2026 12:00:08 -0700 Subject: [PATCH 1/2] added: gfmi_e analysis scripts feat: gfli with outer loop Vdc and Q control --- .../2-bus-src-gfli_e/inputs/buses.csv | 3 + .../2-bus-src-gfli_e/inputs/gfli_e.csv | 2 + .../inputs/infinite_sources.csv | 2 + .../2-bus-src-gfli_e/inputs/lines.csv | 2 + .../2-bus-src-gfli_e/inputs/loads.csv | 3 + .../2-bus-src-gfli_e/inputs/timepoints.csv | 2 + .../active_power_balance_by_bus.csv | 3 + .../outputs/ac_power_flow/bus_voltage.csv | 3 + .../outputs/ac_power_flow/costs_summary.csv | 2 + .../ac_power_flow/generator_dispatch.csv | 3 + .../outputs/ac_power_flow/line_flows.csv | 2 + .../outputs/ac_power_flow/load_shedding.csv | 3 + .../reactive_power_balance_by_bus.csv | 3 + .../outputs/ac_power_flow/solver_status.csv | 5 + .../component_connection_matrices/F.csv | 18 + .../component_connection_matrices/G.csv | 18 + .../component_connection_matrices/H.csv | 11 + .../component_connection_matrices/L.csv | 11 + .../2-bus-src-gfli_e/run.py | 37 + .../2-bus-src-gfmi_e/emt_analysis.py | 202 +++++ .../2-bus-src-gfmi_e/emt_heatmaps.png | Bin 0 -> 93330 bytes .../2-bus-src-gfmi_e/inputs/gfmi_e.csv | 4 +- .../active_power_balance_by_bus.csv | 4 +- .../outputs/ac_power_flow/bus_voltage.csv | 4 +- .../outputs/ac_power_flow/costs_summary.csv | 2 +- .../ac_power_flow/generator_dispatch.csv | 4 +- .../outputs/ac_power_flow/line_flows.csv | 2 +- .../outputs/ac_power_flow/load_shedding.csv | 4 +- .../reactive_power_balance_by_bus.csv | 4 +- .../outputs/ac_power_flow/solver_status.csv | 2 +- .../component_connection_matrices/F.csv | 18 +- .../component_connection_matrices/G.csv | 16 +- .../component_connection_matrices/H.csv | 14 +- .../component_connection_matrices/L.csv | 12 +- .../outputs/small_signal_model/A.csv | 42 +- .../outputs/small_signal_model/B.csv | 18 +- .../outputs/small_signal_model/C.csv | 22 +- .../outputs/small_signal_model/D.csv | 12 +- .../outputs/small_signal_model/u.csv | 14 +- .../outputs/small_signal_model/x.csv | 52 +- .../outputs/small_signal_model/y.csv | 20 +- .../2-bus-src-gfmi_e/run.py | 124 ++- .../2-bus-src-gfmi_e/run_compare_ssm_emt.py | 453 +++++++++++ .../2-bus-src-gfmi_e/ssm_analysis.py | 129 +++ .../2-bus-src-gfmi_e/ssm_heatmaps.png | Bin 0 -> 55762 bytes .../2-bus_src-gfm/emt_analysis.py | 201 +++++ .../2-bus_src-gfm/emt_heatmaps.png | Bin 0 -> 93334 bytes .../2-bus_src-gfm/inputs/buses.csv | 4 +- .../2-bus_src-gfm/inputs/gfmi_c.csv | 2 +- .../active_power_balance_by_bus.csv | 4 +- .../outputs/ac_power_flow/bus_voltage.csv | 4 +- .../outputs/ac_power_flow/costs_summary.csv | 2 +- .../ac_power_flow/generator_dispatch.csv | 4 +- .../outputs/ac_power_flow/line_flows.csv | 2 +- .../outputs/ac_power_flow/load_shedding.csv | 4 +- .../reactive_power_balance_by_bus.csv | 4 +- .../outputs/ac_power_flow/solver_status.csv | 2 +- .../component_connection_matrices/F.csv | 18 +- .../component_connection_matrices/G.csv | 16 +- .../component_connection_matrices/H.csv | 14 +- .../component_connection_matrices/L.csv | 12 +- .../outputs/small_signal_model/A.csv | 36 +- .../outputs/small_signal_model/B.csv | 16 +- .../outputs/small_signal_model/C.csv | 22 +- .../outputs/small_signal_model/D.csv | 12 +- .../outputs/small_signal_model/u.csv | 10 +- .../outputs/small_signal_model/x.csv | 34 +- .../outputs/small_signal_model/y.csv | 20 +- .../small_signal_and_emt/2-bus_src-gfm/run.py | 4 +- .../2-bus_src-gfm/ssm_analysis.py | 157 ++++ .../2-bus_src-gfm/ssm_heatmaps.png | Bin 0 -> 55762 bytes .../2-bus_src_gfli_a/inputs/buses.csv | 3 + .../2-bus_src_gfli_a/inputs/gfli_a.csv | 2 + .../inputs/infinite_sources.csv | 2 + .../2-bus_src_gfli_a/inputs/lines.csv | 2 + .../2-bus_src_gfli_a/inputs/loads.csv | 3 + .../2-bus_src_gfli_a/inputs/timepoints.csv | 2 + .../2-bus_src_gfli_a/run.py | 34 + .../small_signal_and_emt/gfmi_e_v_gfmi_c.py | 275 +++++++ sting/generator/gfli_e.py | 740 ++++++++++++++++++ sting/generator/gfmi_e.py | 98 ++- 81 files changed, 2756 insertions(+), 320 deletions(-) create mode 100644 examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/buses.csv create mode 100755 examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/gfli_e.csv create mode 100644 examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/infinite_sources.csv create mode 100644 examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/lines.csv create mode 100644 examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/loads.csv create mode 100644 examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/timepoints.csv create mode 100644 examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/active_power_balance_by_bus.csv create mode 100644 examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/bus_voltage.csv create mode 100644 examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/costs_summary.csv create mode 100644 examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/generator_dispatch.csv create mode 100644 examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/line_flows.csv create mode 100644 examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/load_shedding.csv create mode 100644 examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/reactive_power_balance_by_bus.csv create mode 100644 examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/solver_status.csv create mode 100644 examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/F.csv create mode 100644 examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/G.csv create mode 100644 examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/H.csv create mode 100644 examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/L.csv create mode 100644 examples/small_signal_and_emt/2-bus-src-gfli_e/run.py create mode 100644 examples/small_signal_and_emt/2-bus-src-gfmi_e/emt_analysis.py create mode 100644 examples/small_signal_and_emt/2-bus-src-gfmi_e/emt_heatmaps.png create mode 100644 examples/small_signal_and_emt/2-bus-src-gfmi_e/run_compare_ssm_emt.py create mode 100644 examples/small_signal_and_emt/2-bus-src-gfmi_e/ssm_analysis.py create mode 100644 examples/small_signal_and_emt/2-bus-src-gfmi_e/ssm_heatmaps.png create mode 100644 examples/small_signal_and_emt/2-bus_src-gfm/emt_analysis.py create mode 100644 examples/small_signal_and_emt/2-bus_src-gfm/emt_heatmaps.png create mode 100644 examples/small_signal_and_emt/2-bus_src-gfm/ssm_analysis.py create mode 100644 examples/small_signal_and_emt/2-bus_src-gfm/ssm_heatmaps.png create mode 100644 examples/small_signal_and_emt/2-bus_src_gfli_a/inputs/buses.csv create mode 100644 examples/small_signal_and_emt/2-bus_src_gfli_a/inputs/gfli_a.csv create mode 100644 examples/small_signal_and_emt/2-bus_src_gfli_a/inputs/infinite_sources.csv create mode 100644 examples/small_signal_and_emt/2-bus_src_gfli_a/inputs/lines.csv create mode 100644 examples/small_signal_and_emt/2-bus_src_gfli_a/inputs/loads.csv create mode 100644 examples/small_signal_and_emt/2-bus_src_gfli_a/inputs/timepoints.csv create mode 100644 examples/small_signal_and_emt/2-bus_src_gfli_a/run.py create mode 100644 examples/small_signal_and_emt/gfmi_e_v_gfmi_c.py create mode 100644 sting/generator/gfli_e.py diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/buses.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/buses.csv new file mode 100644 index 0000000..3817d3d --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/buses.csv @@ -0,0 +1,3 @@ +name,base_power_MVA,base_voltage_kV,base_frequency_Hz,minimum_voltage_pu,maximum_voltage_pu +lima,1.00E+02,2.30E+02,60,0.95,1.05 +santiago,1.00E+02,2.30E+02,60,0.95,1.05 \ No newline at end of file diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/gfli_e.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/gfli_e.csv new file mode 100755 index 0000000..491615b --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/gfli_e.csv @@ -0,0 +1,2 @@ +name,bus,minimum_active_power_MW,maximum_active_power_MW,minimum_reactive_power_MVAR,maximum_reactive_power_MVAR,base_power_MVA,base_voltage_kV,base_frequency_Hz,cost_variable_USDperMWh,rf1_pu,lf1_pu,rsh_pu,csh_pu,txr_power_MVA,txr_voltage1_kV,txr_voltage2_kV,txr_r1_pu,txr_l1_pu,txr_r2_pu,txr_l2_pu,beta,kp_pll,ki_pll,kp_cc,ki_cc,vdc_ref,i_load_ref,c_dc,kp_oc,ki_oc +solar,santiago,10,10,0,0,1.00E+02,4.80E-01,60,0,0.02,0.1,10,1,1.00E+02,4.80E-01,2.30E+02,0.01,0.1,0.02,0.1,0,1,10,1,10,2,0,20,1,10 \ No newline at end of file diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/infinite_sources.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/infinite_sources.csv new file mode 100644 index 0000000..9d95931 --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/infinite_sources.csv @@ -0,0 +1,2 @@ +name,bus,minimum_active_power_MW,maximum_active_power_MW,minimum_reactive_power_MVAR,maximum_reactive_power_MVAR,base_power_MVA,base_voltage_kV,base_frequency_Hz,cost_variable_USDperMWh,r_pu,x_pu +gen1,lima,-200,200,-500,500,1.00E+02,2.30E+02,60,0,0.01,0.5 \ No newline at end of file diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/lines.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/lines.csv new file mode 100644 index 0000000..74a86b2 --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/lines.csv @@ -0,0 +1,2 @@ +name,from_bus,to_bus,base_power_MVA,base_voltage_kV,base_frequency_Hz,r_pu,x_pu,g_pu,b_pu +tx_1,lima,santiago,1.00E+02,2.30E+02,60,0.01,0.5,0.05,0.066666667 \ No newline at end of file diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/loads.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/loads.csv new file mode 100644 index 0000000..79d806e --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/loads.csv @@ -0,0 +1,3 @@ +bus,timepoint,load_MW,load_MVAR +lima,t_1,0,0 +chile,t_1,0,0 \ No newline at end of file diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/timepoints.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/timepoints.csv new file mode 100644 index 0000000..ad319a5 --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/timepoints.csv @@ -0,0 +1,2 @@ +name +timepoint_1 \ No newline at end of file diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/active_power_balance_by_bus.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/active_power_balance_by_bus.csv new file mode 100644 index 0000000..bc24fde --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/active_power_balance_by_bus.csv @@ -0,0 +1,3 @@ +bus,timepoint,generator_dispatch_MW,load_shedding_MW,load_MW,net_line_leaving_flow_MW +lima,timepoint_1,-0.058375056098752195,-9.974940964399896e-9,0.0,-0.05837506532163607 +santiago,timepoint_1,10.0,-9.974940964460538e-9,0.0,9.999999989460255 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/bus_voltage.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/bus_voltage.csv new file mode 100644 index 0000000..fa0fc34 --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/bus_voltage.csv @@ -0,0 +1,3 @@ +id,bus,timepoint,voltage_magnitude_pu,voltage_angle_deg +0,lima,timepoint_1,0.9795934248147871,0.0 +1,santiago,timepoint_1,1.013581804636969,1.3637928689337457 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/costs_summary.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/costs_summary.csv new file mode 100644 index 0000000..940fe42 --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/costs_summary.csv @@ -0,0 +1,2 @@ +component,cost +total_cost_USD,-0.00003989976383138582 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/generator_dispatch.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/generator_dispatch.csv new file mode 100644 index 0000000..80a132f --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/generator_dispatch.csv @@ -0,0 +1,3 @@ +id,type,generator,timepoint,active_power_MW,reactive_power_MVAR +0,infinite_sources,gen1,timepoint_1,-0.058375056098752195,-12.902934347861217 +0,gfli_e,solar,timepoint_1,10.0,0.0 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/line_flows.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/line_flows.csv new file mode 100644 index 0000000..2ffcc27 --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/line_flows.csv @@ -0,0 +1,2 @@ +line,from_bus,to_bus,existing_capacity_MW,active_power_from_bus_MW,reactive_power_from_bus_MVAR,active_power_to_bus_MW,reactive_power_to_bus_MVAR,active_power_loss_MW,reactive_power_loss_MVAR +tx_1,lima,santiago,inf,-0.05837506532163335,-12.902934358094463,9.999999989460255,-9.95750355277473e-9,9.94162492413862,-12.902934368051966 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/load_shedding.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/load_shedding.csv new file mode 100644 index 0000000..529532a --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/load_shedding.csv @@ -0,0 +1,3 @@ +bus,timepoint,active_load_shedding_MW,reactive_load_shedding_MVAR +lima,timepoint_1,-9.974940964399896e-9,-9.97494096436451e-9 +santiago,timepoint_1,-9.974940964460538e-9,-9.974940938160877e-9 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/reactive_power_balance_by_bus.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/reactive_power_balance_by_bus.csv new file mode 100644 index 0000000..961177c --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/reactive_power_balance_by_bus.csv @@ -0,0 +1,3 @@ +bus,timepoint,generator_dispatch_MVAR,load_shedding_MVAR,load_MVAR,net_line_leaving_flow_MVAR +lima,timepoint_1,-12.902934347861217,-9.97494096436451e-9,0.0,-12.90293435809444 +santiago,timepoint_1,0.0,-9.974940938160877e-9,0.0,-9.95750355277473e-9 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/solver_status.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/solver_status.csv new file mode 100644 index 0000000..1402c84 --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/solver_status.csv @@ -0,0 +1,5 @@ +attribute,value +solver_name,ipopt +solver_status,ok +termination_condition,optimal +time_spent_seconds,0.10544800758361816 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/F.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/F.csv new file mode 100644 index 0000000..85259ac --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/F.csv @@ -0,0 +1,18 @@ +Index,"('infinite_sources_0', 'i_bus_D')","('infinite_sources_0', 'i_bus_Q')","('gfli_e_0', 'i_bus_D')","('gfli_e_0', 'i_bus_Q')","('shunt_parallel_rc_0', 'v_bus_D')","('shunt_parallel_rc_0', 'v_bus_Q')","('shunt_parallel_rc_1', 'v_bus_D')","('shunt_parallel_rc_1', 'v_bus_Q')","('branch_series_rl_0', 'i_br_D')","('branch_series_rl_0', 'i_br_Q')" +"('infinite_sources_0', 'v_ref_d')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('infinite_sources_0', 'v_ref_q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('infinite_sources_0', 'v_bus_D')",0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0 +"('infinite_sources_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0 +"('gfli_e_0', 'vdc_ref')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfli_e_0', 'i_load_ref')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfli_e_0', 'q_ref')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfli_e_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0 +"('gfli_e_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0 +"('shunt_parallel_rc_0', 'i_bus_D')",1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-1.0,0.0 +"('shunt_parallel_rc_0', 'i_bus_Q')",0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-1.0 +"('shunt_parallel_rc_1', 'i_bus_D')",0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0 +"('shunt_parallel_rc_1', 'i_bus_Q')",0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,1.0 +"('branch_series_rl_0', 'v_from_bus_D')",0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'v_from_bus_Q')",0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'v_to_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'v_to_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/G.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/G.csv new file mode 100644 index 0000000..1beb4b5 --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/G.csv @@ -0,0 +1,18 @@ +Index,"('infinite_sources_0', 'v_ref_d')","('infinite_sources_0', 'v_ref_q')","('gfli_e_0', 'vdc_ref')","('gfli_e_0', 'i_load_ref')","('gfli_e_0', 'q_ref')" +"('infinite_sources_0', 'v_ref_d')",1.0,0.0,0.0,0.0,0.0 +"('infinite_sources_0', 'v_ref_q')",0.0,1.0,0.0,0.0,0.0 +"('infinite_sources_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0 +"('infinite_sources_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0 +"('gfli_e_0', 'vdc_ref')",0.0,0.0,1.0,0.0,0.0 +"('gfli_e_0', 'i_load_ref')",0.0,0.0,0.0,1.0,0.0 +"('gfli_e_0', 'q_ref')",0.0,0.0,0.0,0.0,1.0 +"('gfli_e_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0 +"('gfli_e_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'i_bus_D')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'i_bus_Q')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'i_bus_D')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'i_bus_Q')",0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'v_from_bus_D')",0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'v_from_bus_Q')",0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'v_to_bus_D')",0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'v_to_bus_Q')",0.0,0.0,0.0,0.0,0.0 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/H.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/H.csv new file mode 100644 index 0000000..d2f1694 --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/H.csv @@ -0,0 +1,11 @@ +Index,"('infinite_sources_0', 'i_bus_D')","('infinite_sources_0', 'i_bus_Q')","('gfli_e_0', 'i_bus_D')","('gfli_e_0', 'i_bus_Q')","('shunt_parallel_rc_0', 'v_bus_D')","('shunt_parallel_rc_0', 'v_bus_Q')","('shunt_parallel_rc_1', 'v_bus_D')","('shunt_parallel_rc_1', 'v_bus_Q')","('branch_series_rl_0', 'i_br_D')","('branch_series_rl_0', 'i_br_Q')" +"('infinite_sources_0', 'i_bus_D')",1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('infinite_sources_0', 'i_bus_Q')",0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfli_e_0', 'i_bus_D')",0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfli_e_0', 'i_bus_Q')",0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0 +"('branch_series_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0 +"('branch_series_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/L.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/L.csv new file mode 100644 index 0000000..e6014c3 --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/L.csv @@ -0,0 +1,11 @@ +Index,"('infinite_sources_0', 'v_ref_d')","('infinite_sources_0', 'v_ref_q')","('gfli_e_0', 'vdc_ref')","('gfli_e_0', 'i_load_ref')","('gfli_e_0', 'q_ref')" +"('infinite_sources_0', 'i_bus_D')",0.0,0.0,0.0,0.0,0.0 +"('infinite_sources_0', 'i_bus_Q')",0.0,0.0,0.0,0.0,0.0 +"('gfli_e_0', 'i_bus_D')",0.0,0.0,0.0,0.0,0.0 +"('gfli_e_0', 'i_bus_Q')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/run.py b/examples/small_signal_and_emt/2-bus-src-gfli_e/run.py new file mode 100644 index 0000000..8dcb018 --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/run.py @@ -0,0 +1,37 @@ + +# Import Python standard and third-party packages +from pathlib import Path + +# Import sting package +from sting import main +from sting.system.core import System + +# Step-change input to applied to the system +def step1(t): + return 0.1 if t >= 0.5 else 0.0 + +def step2(t): + return 0.0 + +inputs = { + 'infinite_sources_0': { + 'v_ref_d': step2 + }, + 'gfli_e_0': { + 'i_load_ref': step1 + } + } + +t_max = 2.0 # Simulation length (in seconds) + +# Specify path of the case study directory +case_dir = Path(__file__).resolve().parent + +# Construct system and small-signal model +sys = System.from_csv(case_directory=case_dir) + +# Construct system and small-signal model +_, ssm = main.run_ssm(case_directory=case_dir) +ssm.simulate_ssm(t_max=t_max, inputs=inputs) + +print('\nok') \ No newline at end of file diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/emt_analysis.py b/examples/small_signal_and_emt/2-bus-src-gfmi_e/emt_analysis.py new file mode 100644 index 0000000..d7b8887 --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/emt_analysis.py @@ -0,0 +1,202 @@ +""" + +Analysis of EMT response of GFMI_E v INF bus system to a grid disturbance under different P/Q and different Pref/Pload relationships + +In progress - April 3 (Ruth) + +""" + +# Import Python standard and third-party packages +from pathlib import Path +import numpy as np +import seaborn as sns +import matplotlib.pyplot as plt + +# Import sting package +from sting.system.core import System +from sting.system.operations import SystemModifier +from sting.modules.power_flow.core import ACPowerFlow +from sting.modules.simulation_emt.core import SimulationEMT +from sting.modules.small_signal_modeling.core import SmallSignalModel + +# Specify path of the case study directory +case_dir = Path(__file__).resolve().parent + +# Construct system and small-signal model +def step1(t): + return 0.3 if t >= 0.5 else 0.0 + +def step2(t): + return 0.0 + +def step3(t): + return 0.1 if t > 1.0 else 0.0 + +inputs = {'infinite_sources_0': {'v_ref_d': step1}, + 'gfmi_e_0': {'p_ref': step2, + 'q_ref': step2, + 'v_ref': step2, + 'v_dc_ref': step2, + 'v_s': step2, + 'i_load_ref': step2}} + +t_max = 2.0 + +# Load system from CSV files +sys = System.from_csv(case_directory=case_dir) + +n = 3 +Prange = np.linspace(100,0,n) +Qrange = np.linspace(-50,50,n) + +Sbase = 100 # MVA +vdc_ref = 1.05 # pu + +tps = np.linspace(0, t_max, 500) +dt = tps[1] - tps[0] + +def run_sim(sys, P, Q, Sbase, vdc_ref, factor): + sys.gfmi_e[0].minimum_active_power_MW = -P*factor + sys.gfmi_e[0].maximum_active_power_MW = -P*factor + sys.gfmi_e[0].minimum_reactive_power_MVAR = Q + sys.gfmi_e[0].maximum_reactive_power_MVAR = Q + sys.gfmi_e[0].i_load_ref = P/Sbase/vdc_ref + + # Run power flow + pf = ACPowerFlow(system=sys, model_settings=None, solver_settings=None) + pf.solve() + + # Break down lines into branches and shunts for small-signal modeling + sys_modifier = SystemModifier(system=sys) + sys_modifier.decompose_lines() + sys_modifier.combine_shunts() + + # Construct small-signal model + ssm = SmallSignalModel(system=sys) + ssm.construct_system_ssm() + + emt_sc = SimulationEMT(system=sys) + emt_sc.sim(t_max, inputs) + return emt_sc + + +# Case 1: Pref = Pload +results_rocof = np.zeros([Prange.shape[0],Qrange.shape[0]]) +results_nadir = np.zeros([Prange.shape[0],Qrange.shape[0]]) + +i = 0 +for P in Prange: + j = 0 + for Q in Qrange: + emt_sc = run_sim(sys, P, Q, Sbase, vdc_ref, 1.0) + + # Measure some performance metrics - frequency ROCOF and nadir and steady state error ? + gfm = emt_sc.system.gfmi_e[0].variables_emt.x.value + w_pc = gfm[1,:] + # nadir + nadir = np.min(w_pc) + results_nadir[i,j] = nadir + # rocof - calculate as a moving average of duration 100ms (~25 timesteps for us) + df_dt = np.abs(np.diff(w_pc)/dt) # calculate raw rocof + df_dt_ma = np.convolve(df_dt,np.ones(25)/25) # get moving averages over 25 time steps (~100ms) + rocof = np.max(df_dt_ma) + + results_rocof[i,j] = rocof + j += 1 + i += 1 + +# Plot results +fig, axes = plt.subplots(nrows=2,ncols=3, figsize=(30,15)) + +sns.heatmap(results_nadir, xticklabels=Qrange, yticklabels=Prange, linewidth=0.5, ax=axes[0,1], cbar=True, cbar_kws = {'label': 'nadir'}) +axes[0,1].set_xlabel("Q_sh") +axes[0,1].set_ylabel("P_load") +axes[0,1].set_title("Pref = Pload") + +sns.heatmap(results_rocof, xticklabels=Qrange, yticklabels=Prange, linewidth=0.5, ax=axes[1,1], cbar=True, cbar_kws = {'label': 'rocof'}) +axes[1,1].set_xlabel("Q_sh") +axes[1,1].set_ylabel("P_load") +axes[1,1].set_title("Pref = Pload") + + +# Case 2: Pref < Pload (Pref=0.8*Pload) + +results_rocof = np.zeros([Prange.shape[0],Qrange.shape[0]]) +results_nadir = np.zeros([Prange.shape[0],Qrange.shape[0]]) + +i = 0 +for P in Prange: + j = 0 + for Q in Qrange: + emt_sc = run_sim(sys, P, Q, Sbase, vdc_ref, 0.8) + + # Measure some performance metrics - frequency ROCOF and nadir and steady state error ? + gfm = emt_sc.system.gfmi_e[0].variables_emt.x.value + w_pc = gfm[1,:] + # nadir + nadir = np.min(w_pc) + results_nadir[i,j] = nadir + # rocof - calculate as a moving average of duration 100ms (~25 timesteps for us) + df_dt = np.abs(np.diff(w_pc)/dt) # calculate raw rocof + df_dt_ma = np.convolve(df_dt,np.ones(25)/25) # get moving averages over 25 time steps (~100ms) + rocof = np.max(df_dt_ma) + + results_rocof[i,j] = rocof + j += 1 + i += 1 + +# Plot results + +sns.heatmap(results_nadir, xticklabels=Qrange, yticklabels=Prange, linewidth=0.5, ax=axes[0,0], cbar=True, cbar_kws = {'label': 'nadir'}) +axes[0,0].set_xlabel("Q_sh") +axes[0,0].set_ylabel("P_load") +axes[0,0].set_title("Pref = 0.8*Pload") + +sns.heatmap(results_rocof, xticklabels=Qrange, yticklabels=Prange, linewidth=0.5, ax=axes[1,0], cbar=True, cbar_kws = {'label': 'rocof'}) +axes[1,0].set_xlabel("Q_sh") +axes[1,0].set_ylabel("P_load") +axes[1,0].set_title("Pref = 0.8*Pload") + + +# Case 3: Pref > Pload (Pref=1.2*Pload) + +results_rocof = np.zeros([Prange.shape[0],Qrange.shape[0]]) +results_nadir = np.zeros([Prange.shape[0],Qrange.shape[0]]) + +i = 0 +for P in Prange: + j = 0 + for Q in Qrange: + emt_sc = run_sim(sys, P, Q, Sbase, vdc_ref, 1.2) + + # Measure some performance metrics - frequency ROCOF and nadir and steady state error ? + gfm = emt_sc.system.gfmi_e[0].variables_emt.x.value + w_pc = gfm[1,:] + # nadir + nadir = np.min(w_pc) + results_nadir[i,j] = nadir + # rocof - calculate as a moving average of duration 100ms (~25 timesteps for us) + df_dt = np.abs(np.diff(w_pc)/dt) # calculate raw rocof + df_dt_ma = np.convolve(df_dt,np.ones(25)/25) # get moving averages over 25 time steps (~100ms) + rocof = np.max(df_dt_ma) + + results_rocof[i,j] = rocof + j += 1 + i += 1 + +# Plot results + +sns.heatmap(results_nadir, xticklabels=Qrange, yticklabels=Prange, linewidth=0.5, ax=axes[0,2], cbar=True, cbar_kws = {'label': 'nadir'}) +axes[0,2].set_xlabel("Q_sh") +axes[0,2].set_ylabel("P_load") +axes[0,2].set_title("Pref = 1.2*Pload") + +sns.heatmap(results_rocof, xticklabels=Qrange, yticklabels=Prange, linewidth=0.5, ax=axes[1,2], cbar=True, cbar_kws = {'label': 'rocof'}) +axes[1,2].set_xlabel("Q_sh") +axes[1,2].set_ylabel("P_load") +axes[1,2].set_title("Pref = 1.2*Pload") + +plt.show() +plt.savefig(str(case_dir)+"/emt_heatmaps.png") + +print('ok') \ No newline at end of file diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/emt_heatmaps.png b/examples/small_signal_and_emt/2-bus-src-gfmi_e/emt_heatmaps.png new file mode 100644 index 0000000000000000000000000000000000000000..3855df09961b4e8ce86d81b5efd902c28ac597d7 GIT binary patch literal 93330 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


X}yq`~7H1j3(W~w|9&QBpY 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 literal 0 HcmV?d00001 diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/inputs/gfmi_e.csv b/examples/small_signal_and_emt/2-bus-src-gfmi_e/inputs/gfmi_e.csv index 8ae66d8..5e0b55d 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfmi_e/inputs/gfmi_e.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/inputs/gfmi_e.csv @@ -1,2 +1,2 @@ -name,bus,minimum_active_power_MW,maximum_active_power_MW,minimum_reactive_power_MVAR,maximum_reactive_power_MVAR,base_power_MVA,base_voltage_kV,base_frequency_Hz,cost_variable_USDperMWh,rf1_pu,xf1_pu,rsh_pu,csh_pu,txr_power_MVA,txr_voltage1_kV,txr_voltage2_kV,txr_r1_pu,txr_x1_pu,txr_r2_pu,txr_x2_pu,h_s,kd_pu,droop_q_pu,tau_pc_s,kp_vc_pu,ki_vc_puHz,kp_v_dc,ki_v_dc,kp_i_L,ki_i_L,l_dc,c_dc,v_dc_ref,v_s,Ti_L,Tv_dc,Ti_dc,Kff_idc,Kff_iload,Ti_load,Tload,i_load_ref -solar,santiago,-10,-10,0,0,1.00E+02,4.80E-01,60,0,0.01,0.1,10000,0.1,1.00E+02,4.80E-01,2.30E+02,0.01,0.1,0.02,0.1,0.5,70,0.01,0.001,1,10,1.2,20,1,10,1,20,1.0,0.5,0.01,0.01,0.01,1,1,0.01,0.001,0.1 \ No newline at end of file +name,bus,minimum_active_power_MW,maximum_active_power_MW,minimum_reactive_power_MVAR,maximum_reactive_power_MVAR,base_power_MVA,base_voltage_kV,base_frequency_Hz,cost_variable_USDperMWh,rf1_pu,xf1_pu,rsh_pu,csh_pu,txr_power_MVA,txr_voltage1_kV,txr_voltage2_kV,txr_r1_pu,txr_x1_pu,txr_r2_pu,txr_x2_pu,h_s,kd_pu,droop_q_pu,tau_pc_s,kp_vc_pu,ki_vc_puHz,kp_v_dc,ki_v_dc,kp_i_L,ki_i_L,l_dc,c_dc,v_dc_ref,v_s,Ti_L,Tv_dc,Ti_dc,Kff_idc,Kff_iload,Ti_load,Tload,i_load_ref,Pbat_max_pu,SOC_max_pu,SOC_init_pu +solar,santiago,-50,-50,-10,10,1.00E+02,4.80E-01,60,0,0.02,0.1,10,1,1.00E+02,4.80E-01,2.30E+02,0.01,0.1,0.02,0.1,0.5,70,0.01,0.001,1,10,1.2,20,1,10,0.1,20,1.05,0.5,0.01,0.01,0.01,1,1,0.01,0.001,0.5,1.5,0.25,0.125 \ No newline at end of file diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/active_power_balance_by_bus.csv b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/active_power_balance_by_bus.csv index c0a07a8..43499bd 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/active_power_balance_by_bus.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/active_power_balance_by_bus.csv @@ -1,3 +1,3 @@ bus,timepoint,generator_dispatch_MW,load_shedding_MW,load_MW,net_line_leaving_flow_MW -lima,timepoint_1,20.024029596964457,-9.99090909090909e-9,0.0,20.024029586973448 -santiago,timepoint_1,-10.0,-9.990909090909092e-9,0.0,-10.000000009990726 +lima,timepoint_1,60.31569213226618,-9.974940964403198e-9,0.0,60.31569212229119 +santiago,timepoint_1,-50.0,-9.974940964403193e-9,0.0,-50.00000000997488 diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/bus_voltage.csv b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/bus_voltage.csv index 753a447..d17c3a2 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/bus_voltage.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/bus_voltage.csv @@ -1,3 +1,3 @@ id,bus,timepoint,voltage_magnitude_pu,voltage_angle_deg -0,lima,timepoint_1,0.9850307325446462,0.0 -1,santiago,timepoint_1,1.0144691438583457,-4.385666517431731 +0,lima,timepoint_1,1.0039676883731015,0.0 +1,santiago,timepoint_1,0.9966223958255749,-15.986449720491722 diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/costs_summary.csv b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/costs_summary.csv index 6122372..22bb914 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/costs_summary.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/costs_summary.csv @@ -1,2 +1,2 @@ component,cost -total_cost_USD,-0.00003996363636363637 +total_cost_USD,-0.00003989976385761279 diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/generator_dispatch.csv b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/generator_dispatch.csv index c8329f2..22fa1bb 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/generator_dispatch.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/generator_dispatch.csv @@ -1,3 +1,3 @@ id,type,generator,timepoint,active_power_MW,reactive_power_MVAR -0,infinite_sources,gen1,timepoint_1,20.024029596964457,-11.986372758049026 -0,gfmi_e,solar,timepoint_1,-10.0,0.0 +0,infinite_sources,gen1,timepoint_1,60.31569213226618,1.388783529105015 +0,gfmi_e,solar,timepoint_1,-50.0,0.7526101226466527 diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/line_flows.csv b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/line_flows.csv index efe99e5..6eac7b5 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/line_flows.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/line_flows.csv @@ -1,2 +1,2 @@ line,from_bus,to_bus,existing_capacity_MW,active_power_from_bus_MW,reactive_power_from_bus_MVAR,active_power_to_bus_MW,reactive_power_to_bus_MVAR,active_power_loss_MW,reactive_power_loss_MVAR -tx_1,lima,santiago,inf,20.02402958697347,-11.986372768040068,-10.000000009990744,-9.99095410228382e-9,10.024029576982725,-11.986372778031022 +tx_1,lima,santiago,inf,60.31569212229122,1.3887835191300466,-50.00000000997491,0.7526101126717135,10.315692112316306,2.14139363180176 diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/load_shedding.csv b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/load_shedding.csv index 8c5a706..2061806 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/load_shedding.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/load_shedding.csv @@ -1,3 +1,3 @@ bus,timepoint,active_load_shedding_MW,reactive_load_shedding_MVAR -lima,timepoint_1,-9.99090909090909e-9,-9.99090909090909e-9 -santiago,timepoint_1,-9.990909090909092e-9,-9.990909090909097e-9 +lima,timepoint_1,-9.974940964403198e-9,-9.9749409644032e-9 +santiago,timepoint_1,-9.974940964403193e-9,-9.97494096440319e-9 diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/reactive_power_balance_by_bus.csv b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/reactive_power_balance_by_bus.csv index 726b458..1f256f2 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/reactive_power_balance_by_bus.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/reactive_power_balance_by_bus.csv @@ -1,3 +1,3 @@ bus,timepoint,generator_dispatch_MVAR,load_shedding_MVAR,load_MVAR,net_line_leaving_flow_MVAR -lima,timepoint_1,-11.986372758049026,-9.99090909090909e-9,0.0,-11.986372768040068 -santiago,timepoint_1,0.0,-9.990909090909097e-9,0.0,-9.990909050803768e-9 +lima,timepoint_1,1.388783529105015,-9.9749409644032e-9,0.0,1.3887835191300466 +santiago,timepoint_1,0.7526101226466527,-9.97494096440319e-9,0.0,0.7526101126717357 diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/solver_status.csv b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/solver_status.csv index 6b473ea..9d22778 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/solver_status.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/ac_power_flow/solver_status.csv @@ -2,4 +2,4 @@ attribute,value solver_name,ipopt solver_status,ok termination_condition,optimal -time_spent_seconds,0.9590749740600586 +time_spent_seconds,0.11365103721618652 diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/component_connection_matrices/F.csv b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/component_connection_matrices/F.csv index e41178d..435c050 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/component_connection_matrices/F.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/component_connection_matrices/F.csv @@ -1,4 +1,4 @@ -Index,"('infinite_sources_0', 'i_bus_D')","('infinite_sources_0', 'i_bus_Q')","('gfmi_e_0', 'i_bus_D')","('gfmi_e_0', 'i_bus_Q')","('pa_rc_0', 'v_bus_D')","('pa_rc_0', 'v_bus_Q')","('pa_rc_1', 'v_bus_D')","('pa_rc_1', 'v_bus_Q')","('se_rl_0', 'i_br_D')","('se_rl_0', 'i_br_Q')" +Index,"('infinite_sources_0', 'i_bus_D')","('infinite_sources_0', 'i_bus_Q')","('gfmi_e_0', 'i_bus_D')","('gfmi_e_0', 'i_bus_Q')","('shunt_parallel_rc_0', 'v_bus_D')","('shunt_parallel_rc_0', 'v_bus_Q')","('shunt_parallel_rc_1', 'v_bus_D')","('shunt_parallel_rc_1', 'v_bus_Q')","('branch_series_rl_0', 'i_br_D')","('branch_series_rl_0', 'i_br_Q')" "('infinite_sources_0', 'v_ref_d')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('infinite_sources_0', 'v_ref_q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('infinite_sources_0', 'v_bus_D')",0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0 @@ -11,11 +11,11 @@ Index,"('infinite_sources_0', 'i_bus_D')","('infinite_sources_0', 'i_bus_Q')","( "('gfmi_e_0', 'i_load_ref')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_e_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0 "('gfmi_e_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0 -"('pa_rc_0', 'i_bus_D')",1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-1.0,0.0 -"('pa_rc_0', 'i_bus_Q')",0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-1.0 -"('pa_rc_1', 'i_bus_D')",0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0 -"('pa_rc_1', 'i_bus_Q')",0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,1.0 -"('se_rl_0', 'v_from_bus_D')",0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'v_from_bus_Q')",0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'v_to_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0 -"('se_rl_0', 'v_to_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0 +"('shunt_parallel_rc_0', 'i_bus_D')",1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-1.0,0.0 +"('shunt_parallel_rc_0', 'i_bus_Q')",0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-1.0 +"('shunt_parallel_rc_1', 'i_bus_D')",0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0 +"('shunt_parallel_rc_1', 'i_bus_Q')",0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,1.0 +"('branch_series_rl_0', 'v_from_bus_D')",0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'v_from_bus_Q')",0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'v_to_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'v_to_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0 diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/component_connection_matrices/G.csv b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/component_connection_matrices/G.csv index 72d52df..9d27ee0 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/component_connection_matrices/G.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/component_connection_matrices/G.csv @@ -11,11 +11,11 @@ Index,"('infinite_sources_0', 'v_ref_d')","('infinite_sources_0', 'v_ref_q')","( "('gfmi_e_0', 'i_load_ref')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 "('gfmi_e_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_e_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'i_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'i_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_1', 'i_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_1', 'i_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'v_from_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'v_from_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'v_to_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'v_to_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'i_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'i_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'i_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'i_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'v_from_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'v_from_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'v_to_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'v_to_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/component_connection_matrices/H.csv b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/component_connection_matrices/H.csv index ba4ffa4..1358a61 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/component_connection_matrices/H.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/component_connection_matrices/H.csv @@ -1,11 +1,11 @@ -Index,"('infinite_sources_0', 'i_bus_D')","('infinite_sources_0', 'i_bus_Q')","('gfmi_e_0', 'i_bus_D')","('gfmi_e_0', 'i_bus_Q')","('pa_rc_0', 'v_bus_D')","('pa_rc_0', 'v_bus_Q')","('pa_rc_1', 'v_bus_D')","('pa_rc_1', 'v_bus_Q')","('se_rl_0', 'i_br_D')","('se_rl_0', 'i_br_Q')" +Index,"('infinite_sources_0', 'i_bus_D')","('infinite_sources_0', 'i_bus_Q')","('gfmi_e_0', 'i_bus_D')","('gfmi_e_0', 'i_bus_Q')","('shunt_parallel_rc_0', 'v_bus_D')","('shunt_parallel_rc_0', 'v_bus_Q')","('shunt_parallel_rc_1', 'v_bus_D')","('shunt_parallel_rc_1', 'v_bus_Q')","('branch_series_rl_0', 'i_br_D')","('branch_series_rl_0', 'i_br_Q')" "('infinite_sources_0', 'i_bus_D')",1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('infinite_sources_0', 'i_bus_Q')",0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_e_0', 'i_bus_D')",0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_e_0', 'i_bus_Q')",0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0 -"('pa_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0 -"('pa_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0 -"('se_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0 -"('se_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +"('shunt_parallel_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0 +"('branch_series_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0 +"('branch_series_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/component_connection_matrices/L.csv b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/component_connection_matrices/L.csv index aa2b8d8..5b2598d 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/component_connection_matrices/L.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/component_connection_matrices/L.csv @@ -3,9 +3,9 @@ Index,"('infinite_sources_0', 'v_ref_d')","('infinite_sources_0', 'v_ref_q')","( "('infinite_sources_0', 'i_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_e_0', 'i_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_e_0', 'i_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/A.csv b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/A.csv index dd0ac99..84befb8 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/A.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/A.csv @@ -1,29 +1,29 @@ -Index,"('infinite_sources_0', 'i_bus_d')","('infinite_sources_0', 'i_bus_q')","('gfmi_e_0', 'angle_pc')","('gfmi_e_0', 'w_pc')","('gfmi_e_0', 'p_pc')","('gfmi_e_0', 'q_pc')","('gfmi_e_0', 'pi_vc')","('gfmi_e_0', 'i_vsc_d')","('gfmi_e_0', 'i_vsc_q')","('gfmi_e_0', 'i_bus_d')","('gfmi_e_0', 'i_bus_q')","('gfmi_e_0', 'v_lcl_sh_d')","('gfmi_e_0', 'v_lcl_sh_q')","('gfmi_e_0', 'i_l_f')","('gfmi_e_0', 'v_dc_f')","('gfmi_e_0', 'i_dc_f')","('gfmi_e_0', 'i_load_f')","('gfmi_e_0', 'x_1')","('gfmi_e_0', 'x_2')","('gfmi_e_0', 'i_L')","('gfmi_e_0', 'v_dc')","('gfmi_e_0', 'i_load')","('pa_rc_0', 'v_bus_D')","('pa_rc_0', 'v_bus_Q')","('pa_rc_1', 'v_bus_D')","('pa_rc_1', 'v_bus_Q')","('se_rl_0', 'i_br_D')","('se_rl_0', 'i_br_Q')" -"('infinite_sources_0', 'i_bus_d')",-7.5398223686155035,376.99111843077515,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-749.3755584175443,-83.21950461965382,0.0,0.0,0.0,0.0 -"('infinite_sources_0', 'i_bus_q')",-376.99111843077515,-7.5398223686155035,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,83.21950461965382,-749.3755584175443,0.0,0.0,0.0,0.0 +Index,"('infinite_sources_0', 'i_bus_d')","('infinite_sources_0', 'i_bus_q')","('gfmi_e_0', 'angle_pc')","('gfmi_e_0', 'w_pc')","('gfmi_e_0', 'p_pc')","('gfmi_e_0', 'q_pc')","('gfmi_e_0', 'pi_vc')","('gfmi_e_0', 'i_vsc_d')","('gfmi_e_0', 'i_vsc_q')","('gfmi_e_0', 'i_bus_d')","('gfmi_e_0', 'i_bus_q')","('gfmi_e_0', 'v_lcl_sh_d')","('gfmi_e_0', 'v_lcl_sh_q')","('gfmi_e_0', 'i_l_f')","('gfmi_e_0', 'v_dc_f')","('gfmi_e_0', 'i_dc_f')","('gfmi_e_0', 'i_load_f')","('gfmi_e_0', 'x_1')","('gfmi_e_0', 'x_2')","('gfmi_e_0', 'i_L')","('gfmi_e_0', 'v_dc')","('gfmi_e_0', 'i_load')","('shunt_parallel_rc_0', 'v_bus_D')","('shunt_parallel_rc_0', 'v_bus_Q')","('shunt_parallel_rc_1', 'v_bus_D')","('shunt_parallel_rc_1', 'v_bus_Q')","('branch_series_rl_0', 'i_br_D')","('branch_series_rl_0', 'i_br_Q')" +"('infinite_sources_0', 'i_bus_d')",-7.5398223686155035,376.99111843077515,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-723.1203801581415,-213.50908482472548,0.0,0.0,0.0,0.0 +"('infinite_sources_0', 'i_bus_q')",-376.99111843077515,-7.5398223686155035,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,213.50908482472548,-723.1203801581415,0.0,0.0,0.0,0.0 "('gfmi_e_0', 'angle_pc')",0.0,0.0,0.0,376.99111843077515,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_e_0', 'w_pc')",0.0,0.0,0.0,-70.0,-1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_e_0', 'p_pc')",0.0,0.0,0.0,0.0,-1000.0,0.0,0.0,0.0,0.0,1011.6644575859594,8.949041881888602,-98.5341583153472,-2.792568273869858,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_e_0', 'q_pc')",0.0,0.0,0.0,0.0,0.0,-1000.0,0.0,0.0,0.0,8.949041881888602,-1011.6644575859594,2.792568273869858,-98.5341583153472,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_e_0', 'pi_vc')",0.0,0.0,0.0,0.0,0.0,-0.1,0.0,0.0,0.0,0.0,0.0,-9.999608776788051,-0.08845513655734374,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_e_0', 'i_vsc_d')",0.0,0.0,0.0,37.086415468269735,0.0,-37.69911184307752,3769.9111843077517,-37.69911184307751,376.99111843077515,0.0,0.0,-7539.674880939275,-33.34680086169996,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_e_0', 'i_vsc_q')",0.0,0.0,0.0,37.44573462619731,0.0,0.0,0.0,-376.99111843077515,-37.69911184307751,0.0,0.0,0.0,-3769.9111843077517,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_e_0', 'i_bus_d')",0.0,0.0,-54.17296510215203,-1.052773436860497,0.0,0.0,0.0,0.0,0.0,-56.54866776461627,376.99111843077515,1884.9555921538758,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-1874.5984341253277,197.32788745394876,0.0,0.0 -"('gfmi_e_0', 'i_bus_q')",0.0,0.0,1911.4617786551519,37.1465025469378,0.0,0.0,0.0,0.0,0.0,-376.99111843077515,-56.54866776461627,0.0,1884.9555921538758,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-197.32788745394876,-1874.5984341253277,0.0,0.0 -"('gfmi_e_0', 'v_lcl_sh_d')",0.0,0.0,0.0,3.3737093079370326,0.0,0.0,0.0,3769.9111843077517,0.0,-3769.9111843077517,0.0,-0.37699111843077515,376.99111843077515,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_e_0', 'v_lcl_sh_q')",0.0,0.0,0.0,-381.3885153419943,0.0,0.0,0.0,0.0,3769.9111843077517,0.0,-3769.9111843077517,-376.99111843077515,-0.37699111843077515,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_e_0', 'p_pc')",0.0,0.0,0.0,0.0,-1000.0,0.0,0.0,0.0,0.0,987.9260565411992,23.78030884341824,-496.76780316078685,-70.54199784602056,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_e_0', 'q_pc')",0.0,0.0,0.0,0.0,0.0,-1000.0,0.0,0.0,0.0,23.78030884341824,-987.9260565411992,70.54199784602056,-496.76780316078685,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_e_0', 'pi_vc')",0.0,0.0,0.0,0.0,0.0,-0.1,0.0,0.0,0.0,0.0,0.0,-9.997104207562575,-0.24063969567519944,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_e_0', 'i_vsc_d')",0.0,0.0,0.0,346.7421388408102,0.0,-37.69911184307752,3769.9111843077517,-75.39822368615502,376.99111843077515,0.0,0.0,-7538.730680585775,-90.71902801143482,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_e_0', 'i_vsc_q')",0.0,0.0,0.0,158.9980800432565,0.0,0.0,0.0,-376.99111843077515,-75.39822368615502,0.0,0.0,0.0,-3769.9111843077517,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_e_0', 'i_bus_d')",0.0,0.0,-236.09093185117854,-26.593706664312624,0.0,0.0,0.0,0.0,0.0,-56.54866776461627,376.99111843077515,1884.9555921538758,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-1732.449388861673,742.7494190000986,0.0,0.0 +"('gfmi_e_0', 'i_bus_q')",0.0,0.0,1863.6945957046444,187.27704971398418,0.0,0.0,0.0,0.0,0.0,-376.99111843077515,-56.54866776461627,0.0,1884.9555921538758,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-742.7494190000986,-1732.449388861673,0.0,0.0 +"('gfmi_e_0', 'v_lcl_sh_d')",0.0,0.0,0.0,8.964965227509495,0.0,0.0,0.0,376.99111843077515,0.0,-376.99111843077515,0.0,-37.69911184307752,376.99111843077515,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_e_0', 'v_lcl_sh_q')",0.0,0.0,0.0,-372.4393489823719,0.0,0.0,0.0,0.0,376.99111843077515,0.0,-376.99111843077515,-376.99111843077515,-37.69911184307752,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_e_0', 'i_l_f')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-100.0,0.0,0.0,0.0,0.0,0.0,100.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_e_0', 'v_dc_f')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-100.0,0.0,0.0,0.0,0.0,0.0,100.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_e_0', 'i_dc_f')",0.0,0.0,0.0,0.0,0.0,0.09932789605777746,-9.932789605777746,100.08337013864903,1.7018489238183393e-16,0.0,0.0,9.932401011992427,0.0878606260974435,0.0,0.0,-100.0,0.0,0.0,0.0,0.0,9.9410705862438,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_e_0', 'i_dc_f')",0.0,0.0,0.0,0.0,0.0,0.40167191080960485,-40.167191080960485,84.52521309107098,1.0406627303014625e-14,0.0,0.0,40.155559496144,0.9665820637849917,0.0,0.0,-100.0,0.0,0.0,0.0,0.0,33.9514038538795,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_e_0', 'i_load_f')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-100.0,0.0,0.0,0.0,0.0,100.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_e_0', 'x_1')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-20.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_e_0', 'x_2')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-10.0,-12.0,10.0,10.0,10.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_e_0', 'i_L')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-376.99111843077515,-452.38934211693015,376.99111843077515,376.99111843077515,376.99111843077515,376.99111843077515,0.0,-188.49555921538757,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_e_0', 'v_dc')",0.0,0.0,0.0,0.0,0.0,-0.018722867313098655,1.8722867313098654,-18.86527082244527,-3.207909645952434e-17,0.0,0.0,-1.8722134831069943,-0.01656133784925169,0.022215865600420028,0.02665903872050403,-0.022215865600420028,-0.022215865600420028,-0.022215865600420028,-0.022215865600420028,9.42477796076938,-1.873847659353666,-18.84955592153876,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_e_0', 'i_L')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-3958.406743523139,-4750.0880922277665,3958.406743523139,3958.406743523139,3958.406743523139,3958.406743523139,0.0,-1795.1958020513098,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_e_0', 'v_dc')",0.0,0.0,0.0,0.0,0.0,-0.07571337144916976,7.571337144916975,-15.932627309401225,-1.9616030330278627e-15,0.0,0.0,-7.569144642832431,-0.18219642664071545,5.680719791051915,6.816863749262298,-5.680719791051915,-5.680719791051915,-5.680719791051915,-5.680719791051915,8.97597901025655,-6.399688855584481,-18.84955592153876,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_e_0', 'i_load')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-1000.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'v_bus_D')",5620.316660029999,-624.1462815266722,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-282.7433374093647,376.99111843077515,0.0,0.0,-5654.8667481872935,0.0 -"('pa_rc_0', 'v_bus_Q')",624.1462815266722,5620.316660029999,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-376.99111843077515,-282.7433374093647,0.0,0.0,0.0,-5654.8667481872935 -"('pa_rc_1', 'v_bus_D')",0.0,0.0,-42.625779353978785,0.0,0.0,0.0,0.0,0.0,0.0,5623.795274257007,591.983659401928,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-282.7433374093647,376.99111843077515,5654.8667481872935,0.0 -"('pa_rc_1', 'v_bus_Q')",0.0,0.0,-555.7890886726366,0.0,0.0,0.0,0.0,0.0,0.0,-591.983659401928,5623.795274257007,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-376.99111843077515,-282.7433374093647,0.0,5654.8667481872935 -"('se_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,753.9822368615503,0.0,-753.9822368615503,0.0,-7.5398223686155035,376.99111843077515 -"('se_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,753.9822368615503,0.0,-753.9822368615503,-376.99111843077515,-7.5398223686155035 +"('shunt_parallel_rc_0', 'v_bus_D')",5423.402824069048,-1601.3181281788504,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-282.7433374093647,376.99111843077515,0.0,0.0,-5654.8667481872935,0.0 +"('shunt_parallel_rc_0', 'v_bus_Q')",1601.3181281788504,5423.402824069048,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-376.99111843077515,-282.7433374093647,0.0,0.0,0.0,-5654.8667481872935 +"('shunt_parallel_rc_1', 'v_bus_D')",0.0,0.0,-740.2906646531766,0.0,0.0,0.0,0.0,0.0,0.0,5197.348140598278,2228.2482458590544,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-282.7433374093647,376.99111843077515,5654.8667481872935,0.0 +"('shunt_parallel_rc_1', 'v_bus_Q')",0.0,0.0,-2739.060301026596,0.0,0.0,0.0,0.0,0.0,0.0,-2228.2482458590544,5197.348140598278,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-376.99111843077515,-282.7433374093647,0.0,5654.8667481872935 +"('branch_series_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,753.9822368615503,0.0,-753.9822368615503,0.0,-7.5398223686155035,376.99111843077515 +"('branch_series_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,753.9822368615503,0.0,-753.9822368615503,-376.99111843077515,-7.5398223686155035 diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/B.csv b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/B.csv index 88c69cc..3553091 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/B.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/B.csv @@ -14,16 +14,16 @@ Index,"('infinite_sources_0', 'v_ref_d')","('infinite_sources_0', 'v_ref_q')","( "('gfmi_e_0', 'v_lcl_sh_q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_e_0', 'i_l_f')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_e_0', 'v_dc_f')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_e_0', 'i_dc_f')",0.0,0.0,0.0,-0.09932789605777746,-9.932789605777746,0.0,0.0,0.0 +"('gfmi_e_0', 'i_dc_f')",0.0,0.0,0.0,-0.4016719108096049,-40.167191080960485,0.0,0.0,0.0 "('gfmi_e_0', 'i_load_f')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_e_0', 'x_1')",0.0,0.0,0.0,0.0,0.0,20.0,0.0,0.0 "('gfmi_e_0', 'x_2')",0.0,0.0,0.0,0.0,0.0,12.0,0.0,0.0 -"('gfmi_e_0', 'i_L')",0.0,0.0,0.0,0.0,0.0,452.38934211693015,376.99111843077515,0.0 -"('gfmi_e_0', 'v_dc')",0.0,0.0,0.0,0.018722867313098655,1.8722867313098654,-0.02665903872050403,0.0,0.0 +"('gfmi_e_0', 'i_L')",0.0,0.0,0.0,0.0,0.0,4750.0880922277665,3769.9111843077517,0.0 +"('gfmi_e_0', 'v_dc')",0.0,0.0,0.0,0.07571337144916976,7.571337144916975,-6.816863749262298,0.0,0.0 "('gfmi_e_0', 'i_load')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,1000.0 -"('pa_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/C.csv b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/C.csv index b1e47fb..7f0ea0e 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/C.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/C.csv @@ -1,11 +1,11 @@ -Index,"('infinite_sources_0', 'i_bus_d')","('infinite_sources_0', 'i_bus_q')","('gfmi_e_0', 'angle_pc')","('gfmi_e_0', 'w_pc')","('gfmi_e_0', 'p_pc')","('gfmi_e_0', 'q_pc')","('gfmi_e_0', 'pi_vc')","('gfmi_e_0', 'i_vsc_d')","('gfmi_e_0', 'i_vsc_q')","('gfmi_e_0', 'i_bus_d')","('gfmi_e_0', 'i_bus_q')","('gfmi_e_0', 'v_lcl_sh_d')","('gfmi_e_0', 'v_lcl_sh_q')","('gfmi_e_0', 'i_l_f')","('gfmi_e_0', 'v_dc_f')","('gfmi_e_0', 'i_dc_f')","('gfmi_e_0', 'i_load_f')","('gfmi_e_0', 'x_1')","('gfmi_e_0', 'x_2')","('gfmi_e_0', 'i_L')","('gfmi_e_0', 'v_dc')","('gfmi_e_0', 'i_load')","('pa_rc_0', 'v_bus_D')","('pa_rc_0', 'v_bus_Q')","('pa_rc_1', 'v_bus_D')","('pa_rc_1', 'v_bus_Q')","('se_rl_0', 'i_br_D')","('se_rl_0', 'i_br_Q')" -"('infinite_sources_0', 'i_bus_D')",0.9938902029533464,-0.11037329601563937,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('infinite_sources_0', 'i_bus_Q')",0.11037329601563937,0.9938902029533464,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_e_0', 'i_bus_D')",0.0,0.0,-0.007537892801389666,0.0,0.0,0.0,0.0,0.0,0.0,0.9945053570112422,0.10468569566059048,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_e_0', 'i_bus_Q')",0.0,0.0,-0.09828509024563639,0.0,0.0,0.0,0.0,0.0,0.0,-0.10468569566059048,0.9945053570112422,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0 -"('pa_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0 -"('pa_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0 -"('se_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0 -"('se_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +Index,"('infinite_sources_0', 'i_bus_d')","('infinite_sources_0', 'i_bus_q')","('gfmi_e_0', 'angle_pc')","('gfmi_e_0', 'w_pc')","('gfmi_e_0', 'p_pc')","('gfmi_e_0', 'q_pc')","('gfmi_e_0', 'pi_vc')","('gfmi_e_0', 'i_vsc_d')","('gfmi_e_0', 'i_vsc_q')","('gfmi_e_0', 'i_bus_d')","('gfmi_e_0', 'i_bus_q')","('gfmi_e_0', 'v_lcl_sh_d')","('gfmi_e_0', 'v_lcl_sh_q')","('gfmi_e_0', 'i_l_f')","('gfmi_e_0', 'v_dc_f')","('gfmi_e_0', 'i_dc_f')","('gfmi_e_0', 'i_load_f')","('gfmi_e_0', 'x_1')","('gfmi_e_0', 'x_2')","('gfmi_e_0', 'i_L')","('gfmi_e_0', 'v_dc')","('gfmi_e_0', 'i_load')","('shunt_parallel_rc_0', 'v_bus_D')","('shunt_parallel_rc_0', 'v_bus_Q')","('shunt_parallel_rc_1', 'v_bus_D')","('shunt_parallel_rc_1', 'v_bus_Q')","('branch_series_rl_0', 'i_br_D')","('branch_series_rl_0', 'i_br_Q')" +"('infinite_sources_0', 'i_bus_D')",0.9590681912721563,-0.2831752187073487,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('infinite_sources_0', 'i_bus_Q')",0.2831752187073487,0.9590681912721563,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_e_0', 'i_bus_D')",0.0,0.0,-0.1309121324371581,0.0,0.0,0.0,0.0,0.0,0.0,0.9190929463128948,0.3940408050416634,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_e_0', 'i_bus_Q')",0.0,0.0,-0.484372209460925,0.0,0.0,0.0,0.0,0.0,0.0,-0.3940408050416634,0.9190929463128948,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0 +"('branch_series_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0 +"('branch_series_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/D.csv b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/D.csv index aa2b8d8..5b2598d 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/D.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/D.csv @@ -3,9 +3,9 @@ Index,"('infinite_sources_0', 'v_ref_d')","('infinite_sources_0', 'v_ref_q')","( "('infinite_sources_0', 'i_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_e_0', 'i_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_e_0', 'i_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/u.csv b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/u.csv index a8d0368..6d1790e 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/u.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/u.csv @@ -1,9 +1,9 @@ name,component,type,init -v_ref_d,infinite_sources_0,device,0.9319147420205057 -v_ref_q,infinite_sources_0,device,2.4364261741631428e-17 -p_ref,gfmi_e_0,device,-0.09970849663622566 -q_ref,gfmi_e_0,device,0.0019433557584956256 -v_ref,gfmi_e_0,device,1.0117040377962803 -v_dc_ref,gfmi_e_0,device,1.0 +v_ref_d,infinite_sources_0,device,1.0602915467925695 +v_ref_q,infinite_sources_0,device,-6.184065849485258e-17 +p_ref,gfmi_e_0,device,-0.4924473672884809 +q_ref,gfmi_e_0,device,0.05787698596992697 +v_ref,gfmi_e_0,device,0.9882122222891866 +v_dc_ref,gfmi_e_0,device,1.05 v_s,gfmi_e_0,device,0.5 -i_load_ref,gfmi_e_0,device,0.1 +i_load_ref,gfmi_e_0,device,0.5 diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/x.csv b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/x.csv index 8fe7525..787fd4f 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/x.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/x.csv @@ -1,29 +1,29 @@ name,component,type,init -i_bus_d,infinite_sources_0,"",0.21547208231583534 -i_bus_q,infinite_sources_0,"",0.09850474697346907 +i_bus_d,infinite_sources_0,"",0.5722653561902081 +i_bus_q,infinite_sources_0,"",-0.18339083649397844 angle_pc,gfmi_e_0,"",0.0 w_pc,gfmi_e_0,"",1.0 -p_pc,gfmi_e_0,"",-0.09970849663622566 -q_pc,gfmi_e_0,"",0.0019433557584956256 -pi_vc,gfmi_e_0,"",1.0008337013864903 -i_vsc_d,gfmi_e_0,"",-0.09932789605777746 -i_vsc_q,gfmi_e_0,"",0.09837477238891429 -i_bus_d,gfmi_e_0,"",-0.0985341583153472 -i_bus_q,gfmi_e_0,"",-0.0027925682738698583 -v_lcl_sh_d,gfmi_e_0,"",1.0116644575859595 -v_lcl_sh_q,gfmi_e_0,"",0.008949041881888602 -i_l_f,gfmi_e_0,"",0.001178588275124015 -v_dc_f,gfmi_e_0,"",1.0 -i_dc_f,gfmi_e_0,"",-0.099410705862438 -i_load_f,gfmi_e_0,"",0.1 -x_1,gfmi_e_0,"",0.0005892941375620075 -x_2,gfmi_e_0,"",0.5 -i_L,gfmi_e_0,"",0.001178588275124015 -v_dc,gfmi_e_0,"",1.0 -i_load,gfmi_e_0,"",0.1 -v_bus_D,pa_rc_0,"",0.9850307325446462 -v_bus_Q,pa_rc_0,"",0.0 -v_bus_D,pa_rc_1,"",1.0114986905096575 -v_bus_Q,pa_rc_1,"",-0.07757604616073832 -i_br_D,se_rl_0,"",0.15403176129835686 -i_br_Q,se_rl_0,"",0.05601655115598958 +p_pc,gfmi_e_0,"",-0.4924473672884809 +q_pc,gfmi_e_0,"",0.05787698596992697 +pi_vc,gfmi_e_0,"",0.8875147374562453 +i_vsc_d,gfmi_e_0,"",-0.42175550635008513 +i_vsc_q,gfmi_e_0,"",0.9197620895795204 +i_bus_d,gfmi_e_0,"",-0.49676780316078684 +i_bus_q,gfmi_e_0,"",-0.07054199784602057 +v_lcl_sh_d,gfmi_e_0,"",0.9879260565411991 +v_lcl_sh_q,gfmi_e_0,"",0.02378030884341824 +i_l_f,gfmi_e_0,"",0.30137154502195707 +v_dc_f,gfmi_e_0,"",1.05 +i_dc_f,gfmi_e_0,"",-0.35648974046573473 +i_load_f,gfmi_e_0,"",0.5 +x_1,gfmi_e_0,"",0.15786128548769174 +x_2,gfmi_e_0,"",0.5238095238095238 +i_L,gfmi_e_0,"",0.30137154502195707 +v_dc,gfmi_e_0,"",1.05 +i_load,gfmi_e_0,"",0.5 +v_bus_D,shunt_parallel_rc_0,"",1.0039676883731015 +v_bus_Q,shunt_parallel_rc_0,"",0.0 +v_bus_D,shunt_parallel_rc_1,"",0.9580798748577896 +v_bus_Q,shunt_parallel_rc_1,"",-0.2744797866029319 +i_br_D,branch_series_rl_0,"",0.5505748558041546 +i_br_Q,branch_series_rl_0,"",-0.08076412991454072 diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/y.csv b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/y.csv index 30a92aa..cf58c36 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/y.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/outputs/small_signal_model/y.csv @@ -1,11 +1,11 @@ name,component,type,init -i_bus_D,infinite_sources_0,"",0.2032832980270174 -i_bus_Q,infinite_sources_0,"",0.12168526688588112 -i_bus_D,gfmi_e_0,"",-0.09828509024563638 -i_bus_Q,gfmi_e_0,"",0.007537892801389665 -v_bus_D,pa_rc_0,"",0.9850307325446462 -v_bus_Q,pa_rc_0,"",0.0 -v_bus_D,pa_rc_1,"",1.0114986905096575 -v_bus_Q,pa_rc_1,"",-0.07757604616073832 -i_br_D,se_rl_0,"",0.15403176129835686 -i_br_Q,se_rl_0,"",0.05601655115598958 +i_bus_D,infinite_sources_0,"",0.6007732403221651 +i_bus_Q,infinite_sources_0,"",-0.013832950454366671 +i_bus_D,gfmi_e_0,"",-0.484372209460925 +i_bus_Q,gfmi_e_0,"",0.1309121324371581 +v_bus_D,shunt_parallel_rc_0,"",1.0039676883731015 +v_bus_Q,shunt_parallel_rc_0,"",0.0 +v_bus_D,shunt_parallel_rc_1,"",0.9580798748577896 +v_bus_Q,shunt_parallel_rc_1,"",-0.2744797866029319 +i_br_D,branch_series_rl_0,"",0.5505748558041546 +i_br_Q,branch_series_rl_0,"",-0.08076412991454072 diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/run.py b/examples/small_signal_and_emt/2-bus-src-gfmi_e/run.py index d862599..2908494 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfmi_e/run.py +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/run.py @@ -1,70 +1,124 @@ + + # In progress - March 5, 2026 - Ruth # Import Python standard and third-party packages from pathlib import Path +from scipy import signal +import numpy as np # Import sting package -from sting.system.core import System -from sting.system.operations import SystemModifier -from sting.modules.power_flow.core import ACPowerFlow -from sting.modules.simulation_emt.core import SimulationEMT -from sting.modules.small_signal_modeling.core import SmallSignalModel +from sting import main +# from sting.system.core import System +# from sting.system.operations import SystemModifier +# from sting.modules.power_flow.core import ACPowerFlow +# from sting.modules.simulation_emt.core import SimulationEMT +# from sting.modules.small_signal_modeling.core import SmallSignalModel # Specify path of the case study directory case_dir = Path(__file__).resolve().parent # Construct system and small-signal model def step1(t): - return 0.1 if t >= 0.5 else 0.0 + return 0.5 if t >= 0.5 else 0.0 def step2(t): return 0.0 def step3(t): - return 0.1 if t > 1.0 else 0.0 + return 0.25 if t > 1.0 else 0.0 + +def step3_neg(t): + return -0.25 if t > 1.0 else 0.0 + +def square_oscillation(t): + osc = 0.1*signal.square(2 * np.pi * 14 * t) + return osc # Specify inputs to excite - any constant input does not need to be specified # NB: input is a perturbation from the nominal value -inputs = {'infinite_sources_0': {'v_ref_d': step1}, - 'gfmi_e_0': {'p_ref': step2, +inputs = {'infinite_sources_0': {'v_ref_d': step2}, + 'gfmi_e_0': {'p_ref': step3_neg, 'q_ref': step2, 'v_ref': step2, 'v_dc_ref': step2, 'v_s': step2, - 'i_load_ref': step2}} + 'i_load_ref': step3}} t_max = 4.0 -# Load system from CSV files -sys = System.from_csv(case_directory=case_dir) +# Construct system and small-signal model +sys, ssm = main.run_ssm(case_directory=case_dir) +ssm.simulate_ssm(t_max=t_max, inputs=inputs) +# Run EMT simulation +main.run_emt(case_directory=case_dir, inputs=inputs, t_max=t_max) + + +# # Load system from CSV files +# sys = System.from_csv(case_directory=case_dir) + +# # Match power reference with load +# P_load = -100 # MW +# sys.gfmi_e[0].minimum_active_power_MW = -P_load +# sys.gfmi_e[0].maximum_active_power_MW = -P_load +# sys.gfmi_e[0].minimum_reactive_power_MVAR = 0 +# sys.gfmi_e[0].maximum_reactive_power_MVAR = 0 + +# # i_load_ref*v_dc_ref = i_load_ref*1 = p_load = i_load_ref +# Sbase = 100 # MVA +# sys.gfmi_e[0].i_load_ref = P_load/Sbase +# sys.gfmi_e[0].i_load_ref = 0 -# Match power reference with load -P_load = 10 # MW -sys.gfmi_e[0].minimum_active_power_MW = -P_load -sys.gfmi_e[0].maximum_active_power_MW = -P_load -sys.gfmi_e[0].minimum_reactive_power_MVAR = 0 -sys.gfmi_e[0].maximum_reactive_power_MVAR = 0 +# # sys.gfmi_e[0].SOC_init_pu = 0.0 +# # sys.gfmi_e[0].Pbat_max_pu = 100.0 +# # sys.gfmi_e[0].v_dc_ref = 1.00 -# i_load_ref*v_dc_ref = i_load_ref*1 = p_load = i_load_ref -Sbase = 100 # MVA -sys.gfmi_e[0].i_load_ref = P_load/Sbase -# Run power flow -pf = ACPowerFlow(system=sys, model_settings=None, solver_settings=None) -pf.solve() +# # Run power flow +# pf = ACPowerFlow(system=sys, model_settings=None, solver_settings=None) +# pf.solve() -# Break down lines into branches and shunts for small-signal modeling -sys_modifier = SystemModifier(system=sys) -sys_modifier.decompose_lines() -sys_modifier.combine_shunts() +# # Break down lines into branches and shunts for small-signal modeling +# sys_modifier = SystemModifier(system=sys) +# sys_modifier.decompose_lines() +# sys_modifier.combine_shunts() + +# # Construct small-signal model +# ssm = SmallSignalModel(system=sys) +# ssm.construct_system_ssm() + +# ssm.simulate_ssm(t_max=t_max, inputs=inputs) + +# emt_sc = SimulationEMT(system=sys) +# emt_sc.sim(t_max, inputs) + +# # calculate SIL + +# # characteristic impedance +# import numpy as np +# l = sys.lines[0] +# Vbase = l.base_voltage_kV*1e3 +# Sbase = l.base_power_MVA*1e6 +# wbase = 2*np.pi*60 +# Zbase = Vbase**2/Sbase +# Ybase = 1/Zbase +# l = sys.lines[0] +# x = l.x_pu*Zbase +# r = l.r_pu*Zbase +# g = l.g_pu*Ybase +# b = l.b_pu*Ybase +# Z0 = np.sqrt((r + x*1j)/(g + b*1j)) + +# # for 230kV line, Z0 should be 360-390 Ohms... + +# Z0_ideal = np.sqrt(x/b) +# SIL_ideal_MW = (Vbase**2/Z0_ideal)/1e6 + +# # Average transmission line parameter values +# # HV (69-230kV) - L=1.3mH/km, c=8.75nF/km -# Construct small-signal model -ssm = SmallSignalModel(system=sys) -ssm.construct_system_ssm() -ssm.simulate_ssm(t_max=t_max, inputs=inputs) -emt_sc = SimulationEMT(system=sys) -emt_sc.sim(t_max, inputs) -print('ok') \ No newline at end of file +print('ok') +# %% diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/run_compare_ssm_emt.py b/examples/small_signal_and_emt/2-bus-src-gfmi_e/run_compare_ssm_emt.py new file mode 100644 index 0000000..1785da0 --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/run_compare_ssm_emt.py @@ -0,0 +1,453 @@ +""" +In progress (March 6, 2026 - Ruth) + +Simulates a a GFMIe connected to an infinite source via a transmission line. + +1. Computes and simulates the small-signal model using STING. + +2. Runs EMT using sting. + +3. Compares corresponding SSM and EMT states in plots. + +""" + +# Import Python standard and third-party packages +import os +import numpy as np +import plotly.graph_objects as go +from plotly.subplots import make_subplots +from pathlib import Path +from typing import Callable + +# Import sting package +from sting import main +from sting.utils.transformations import dq02abc, abc2dq0 +from sting.modules.small_signal_modeling.core import SmallSignalModel +from sting.system.core import System +from sting.system.component import Component +from sting.system.operations import SystemModifier +from sting.modules.power_flow.core import ACPowerFlow +from sting.modules.simulation_emt.core import SimulationEMT + + +# Define additional functions that return required data in order to compare SSM and EMT + +def simulate_ssm_ruth(ssm: SmallSignalModel, t_max: float, inputs: dict[str, dict[str, Callable[[float], float]]] = None, settings={'dense_output': True, 'method': 'Radau', 'max_step': 0.001}): + """Simulate the small-signal model under a given input profile.""" + + x0 = np.zeros_like(ssm.model.x.init) + tps, solution = ssm.model.simulate(t_max=t_max, inputs=inputs, x0=x0, settings=settings, output_directory=ssm.output_directory, plot=False) + + # Add the initial conditions back to the solution (for plotting purposes) + for i in range(len(ssm.model.x.init)): + solution[i] = solution[i] + ssm.model.x.init[i] + + components_to_plot = np.unique(ssm.model.x.component) # Get the components in the same order as solution vector + i = 0 # Initialize counter + + name_list = [] + component_list = [] + # Make a html file for each component. Each file plots the states corresponding to each component. + for component in components_to_plot: + number_of_states = sum(ssm.model.x.component == component) + nrows = int(np.ceil(number_of_states / 2)) + ncols = 2 if number_of_states > 1 else 1 + #fig = make_subplots(rows=nrows, cols=ncols) + for j in range(number_of_states): + row = j // ncols + 1 + col = j % ncols + 1 + #fig.add_trace(go.Scatter(x=tps, y=solution[i]), row=row, col=col) + #fig.update_xaxes(title_text='Time [s]', row=row, col=col) + #fig.update_yaxes(title_text=ssm.model.x.name[i], row=row, col=col) + name_list.append(ssm.model.x.name[i]) # added + component_list.append(component) + i += 1 + + + #fig.update_layout(title_text = component, title_x=0.5, showlegend = False) + #fig.write_html(os.path.join(ssm.output_directory, f"{component}.html")) + + return tps, solution, name_list, component_list + +def run_emt_ruth(sys, t_max, inputs, case_directory=os.getcwd(), model_settings=None, solver_settings=None): + """ + Routine to simulate the EMT dynamics of the system from a case study directory. + """ + + # Load system from CSV files + sys = System.from_csv(case_directory=case_directory) + + # Run power flow + pf = ACPowerFlow(system=sys, model_settings=model_settings, solver_settings=solver_settings) + pf.solve() + + # Break down lines into branches and shunts for small-signal modeling + sys_modifier = SystemModifier(system=sys) + sys_modifier.decompose_lines() + + # Construct small-signal model + ssm = SmallSignalModel(system=sys) + ssm.construct_system_ssm() + + emt_sc = SimulationEMT(system=sys) + emt_sc.sim(t_max, inputs) + + return sys, emt_sc + + +def reconstruct_input_timeseries(fcn_name, tps, init_cond): + output = np.zeros_like(tps) + i = 0 + for t in tps: + output[i] = fcn_name(t) + i += 1 + return output + init_cond # add back initial condition + + +# Specify path of the case study directory +case_dir = Path(__file__).resolve().parent + +# Construct system and small-signal model +def step1(t): + return 0.1 if t >= 0.5 else 0.0 + +def no_step(t): + return 0.0 + +def step3(t): + return 0.1 if t > 1.0 else 0.0 + +def noisy_i_load_ref(t): + avg = 0.1*np.sin(2*np.pi*1*t)/2 # 1 Hz + fast = 0.05*np.sin(2*np.pi*20*t)/2 # 20 Hz + return avg + fast + +def p_ref(t): + return -0.1*np.sin(2*np.pi*1*t) if t < 1 else 0 #1 Hz oscillation + +def slow_small_oscillation(t): + return 0.1*np.sin(2*np.pi*1*t) if t < 1 else 0 #1 Hz oscillation + +# Specify inputs to excite - any constant input does not need to be specified +# NB: input is a perturbation from the nominal value +inputs = {'infinite_sources_0': {'v_ref_d': no_step}, + 'gfmi_e_0': {'p_ref': step1, + 'q_ref': no_step, + 'v_ref': no_step, + 'v_dc_ref': no_step, + 'v_s': no_step, + 'i_load_ref': slow_small_oscillation}} + +t_max = 4.0 + +# Load system from CSV files +sys = System.from_csv(case_directory=case_dir) + +# Run power flow +pf = ACPowerFlow(system=sys, model_settings=None, solver_settings=None) +pf.solve() + +# Build and perturb small-signal model +sys, ssm = main.run_ssm(case_directory=case_dir) +tps, sol, ssm_state_names, component_name = simulate_ssm_ruth(ssm, t_max=t_max, inputs=inputs) + +# Retrieve state traces +i_bus_d_inf = sol[0,:] # infinite source +i_bus_q_inf = sol[1,:] # infinite source +angle_pc = sol[2,:] +w_pc = sol[3,:] +p_pc = sol[4,:] +q_pc = sol[5,:] +pi_vc = sol[6,:] +i_vsc_d = sol[7,:] +i_vsc_q = sol[8,:] +i_bus_d = sol[9,:] # gfmie +i_bus_q = sol[10,:] # gfmie +v_sh_d = sol[11,:] +v_sh_q = sol[12,:] +iLf = sol[13,:] +vdcf = sol[14,:] +idcf = sol[15,:] +iloadf = sol[16,:] +x1 = sol[17,:] +x2 = sol[18,:] +iL = sol[19,:] +vdc = sol[20,:] +i_load = sol[21,:] +v_bus_D_rc0 = sol[22,:] # RC0 +v_bus_Q_rc0 = sol[23,:] # RC0 +v_bus_D_rc1 = sol[24,:] #RC1 +v_bus_Q_rc1 = sol[25,:] #RC1 +i_br_D_br0 = sol[26,:] #BR0 +i_br_Q_br0 = sol[27,:] #BR0 + +# Run EMT + +emt_sc = SimulationEMT(system=sys) +emt_sc.sim(t_max, inputs) + +emt_state_names = emt_sc.variables.x.name +# Define timepoints that will be used to evaluate the solution of the ODEs +tps = np.linspace(0, t_max, 500) +n_tps = len(tps) + +# Extract solutions directly from each component +gfm = emt_sc.system.gfmi_e[0].variables_emt.x.value +gfm_names = emt_sc.system.gfmi_e[0].variables_emt.x.name + +angle_pc_emt = gfm[0,:] +w_pc_emt = gfm[1,:] +p_pc_emt = gfm[2,:] +q_pc_emt = gfm[3,:] +gamma_emt = gfm[4,:] +i_vsc_a = gfm[5,:] +i_vsc_b = gfm[6,:] +i_vsc_c = gfm[7,:] +v_sh_a = gfm[8,:] +v_sh_b = gfm[9,:] +v_sh_c = gfm[10,:] +i_bus_a = gfm[11,:] +i_bus_b = gfm[12,:] +i_bus_c = gfm[13,:] +iLf_emt = gfm[14,:] +vdcf_emt = gfm[15,:] +idcf_emt = gfm[16,:] +iloadf_emt = gfm[17,:] +x1_emt = gfm[18,:] +x2_emt = gfm[19,:] +iL_emt = gfm[20,:] +vdc_emt = gfm[21,:] +i_load_emt = gfm[22,:] + +inf_src = emt_sc.system.infinite_sources[0].variables_emt.x.value + +# convert abc to dq for plotting comparison +angle_pc_emt_init = sys.gfmi_e[0].emt_init.angle_ref * np.pi / 180 + +i_bus_d_emt, i_bus_q_emt, _ = zip(*[abc2dq0(a, b, c, ang) for a, b, c, ang in zip(i_bus_a, i_bus_b, i_bus_c, angle_pc_emt)]) #? what angle to use here + +i_vsc_d_emt, i_vsc_q_emt, _ = zip(*[abc2dq0(a, b, c, ang) for a, b, c, ang in zip(i_vsc_a, i_vsc_b, i_vsc_c, angle_pc_emt)]) + +v_sh_d_emt, v_sh_q_emt, _ = zip(*[abc2dq0(a, b, c, ang) for a, b, c, ang in zip(v_sh_a, v_sh_b, v_sh_c, angle_pc_emt)]) + +fig = make_subplots( + rows=14, cols=2, + horizontal_spacing=0.15, + vertical_spacing=0.05, +) + +r, c = 1,1 # define row, column for convenience +# plot inf source voltages? +fig.add_trace(go.Scatter(x=tps, y=angle_pc_emt, name="angle_pc (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup='1'), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=angle_pc, name="angle_pc (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup='1'), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='angle_pc', row=r, col=c) + +r, c = 1,2 +fig.add_trace(go.Scatter(x=tps, y=angle_pc_emt, name="angle_pc (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup='1'), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=angle_pc, name="angle_pc (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup='1'), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='angle_pc', row=r, col=c) + + +r, c = 2,1 +fig.add_trace(go.Scatter(x=tps, y=gamma_emt, name="gamma (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=pi_vc, name="gamma (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='gamma', row=r, col=c) + +r, c = 2, 2 +fig.add_trace(go.Scatter(x=tps, y=w_pc_emt, name="w_pc (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=w_pc, name="w_pc (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup=str(r)), row=r, col=c) + +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='w_pc', row=r, col=c) + +r, c = 3,1 +fig.add_trace(go.Scatter(x=tps, y=p_pc_emt, name="p_pc (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=p_pc, name="p_pc (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup=str(r)), row=r, col=c) + +pref = reconstruct_input_timeseries(inputs['gfmi_e_0']['p_ref'], tps, sys.gfmi_e[0].emt_init.p_ref) +fig.add_trace(go.Scatter(x=tps, y=pref, name="p_ref", mode='lines', line=dict(color='green', dash='dot'), legendgroup=str(r)), row=r, col=c) + +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='p_pc', row=r, col=c) + +r, c = 3,2 +fig.add_trace(go.Scatter(x=tps, y=q_pc_emt, name="q_pc (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=q_pc, name="q_pc (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup=str(r)), row=r, col=c) +qref = reconstruct_input_timeseries(inputs['gfmi_e_0']['q_ref'], tps, sys.gfmi_e[0].emt_init.q_ref) +fig.add_trace(go.Scatter(x=tps, y=qref, name="q_ref", mode='lines', line=dict(color='green', dash='dot'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='q_pc', row=r, col=c) + +r, c = 4,1 +fig.add_trace(go.Scatter(x=tps, y=i_vsc_d_emt, name="i_vsc_d (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=i_vsc_d, name="i_vsc_d (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='i_vsc_d', row=r, col=c) + +r, c = 4,2 +fig.add_trace(go.Scatter(x=tps, y=i_vsc_q_emt, name="i_vsc_q (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=i_vsc_q, name="i_vsc_q (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='i_vsc_q', row=r, col=c) + + +r, c = 5,1 +fig.add_trace(go.Scatter(x=tps, y=v_sh_d_emt, name="v_sh_d (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=v_sh_d, name="v_sh_d (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='v_sh_d', row=r, col=c) + + +r, c = 5,2 +fig.add_trace(go.Scatter(x=tps, y=v_sh_q_emt, name="v_sh_q (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=v_sh_q, name="v_sh_q (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='v_sh_q', row=r, col=c) + +r, c = 6,1 +fig.add_trace(go.Scatter(x=tps, y=i_bus_d_emt, name="i_bus_d (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=i_bus_d, name="i_bus_d (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='i_bus_d', row=r, col=c) + +r, c = 6,2 +fig.add_trace(go.Scatter(x=tps, y=i_bus_q_emt, name="i_bus_q (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=i_bus_q, name="i_bus_q (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='i_bus_q', row=r, col=c) + +r, c = 7,1 +fig.add_trace(go.Scatter(x=tps, y=iLf_emt, name="iLf (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=iLf, name="iLf (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='iLf', row=r, col=c) + + +r, c = 7,2 +fig.add_trace(go.Scatter(x=tps, y=vdcf_emt, name="vdcf (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=vdcf, name="vdcf (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='vdcf', row=r, col=c) + +r, c = 8,1 +fig.add_trace(go.Scatter(x=tps, y=idcf_emt, name="idcf (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=idcf, name="idcf (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='idcf', row=r, col=c) + +r, c = 8,2 +fig.add_trace(go.Scatter(x=tps, y=iloadf_emt, name="iloadf (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=iloadf, name="iloadf (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='iloadf', row=r, col=c) + +r, c = 9,1 +fig.add_trace(go.Scatter(x=tps, y=x1_emt, name="x1 (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=x1, name="x1 (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='x1', row=r, col=c) + +r, c = 9,2 +fig.add_trace(go.Scatter(x=tps, y=x2_emt, name="x2 (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=x2, name="x2 (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='x2', row=r, col=c) + + +r, c = 10,1 +fig.add_trace(go.Scatter(x=tps, y=iL_emt, name="iL (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=iL, name="iL (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='iL', row=r, col=c) + +r, c = 10,2 +fig.add_trace(go.Scatter(x=tps, y=vdc_emt, name="vdc (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=vdc, name="vdc (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup=str(r)), row=r, col=c) +vdc_ref = reconstruct_input_timeseries(inputs['gfmi_e_0']['v_dc_ref'], tps, sys.gfmi_e[0].emt_init.v_dc) +fig.add_trace(go.Scatter(x=tps, y=vdc_ref, name="vdc_ref", mode='lines', line=dict(color='green', dash='dot'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='vdc', row=r, col=c) + +r, c = 11,1 +fig.add_trace(go.Scatter(x=tps, y=i_load_emt, name="iload (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=i_load, name="iload (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup=str(r)), row=r, col=c) +iload_ref = reconstruct_input_timeseries(inputs['gfmi_e_0']['i_load_ref'], tps, sys.gfmi_e[0].emt_init.i_load) +fig.add_trace(go.Scatter(x=tps, y=iload_ref, name="i_load_ref", mode='lines', line=dict(color='green', dash='dot'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='iload', row=r, col=c) + +r, c = 11, 2 +pload_emt = i_load_emt*vdc_emt +pload = i_load*vdc + +fig.add_trace(go.Scatter(x=tps, y=pload_emt, name="pload (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=pload, name="pload (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='pload (calculated)', row=r, col=c) + +r, c = 12, 1 + +pbattery_emt = iL_emt*sys.gfmi_e[0].v_s # needs fixing if we perturb v_s +pbattery = iL*sys.gfmi_e[0].v_s # needs fixing if we perturb v_s + +fig.add_trace(go.Scatter(x=tps, y=pbattery_emt, name="p_battery (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=pbattery, name="p_battery (ssm)", mode='lines', line=dict(color='blue', dash='dot'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='p_battery (calculated)', row=r, col=c) + +r, c = 13, 1 + +# power comparisons +g = sys.gfmi_e[0] +v_vsc_d_emt = v_sh_d_emt + np.multiply(g.rf1_pu, i_vsc_d_emt) - np.multiply(g.xf1_pu, i_vsc_q_emt) +v_vsc_q_emt = v_sh_q_emt + np.multiply(g.rf1_pu, i_vsc_q_emt) + np.multiply(g.xf1_pu, i_vsc_d_emt) + +p_ac_emt = np.multiply(i_vsc_d_emt,v_vsc_d_emt) + np.multiply(i_vsc_q_emt,v_vsc_q_emt) +idc_emt = p_ac_emt/vdc_emt + +duty_cycle_emt = g.kp_i_L*(g.kp_v_dc*(g.v_dc_ref - vdcf_emt) + x1_emt - iLf_emt + g.Kff_idc*idcf_emt + g.Kff_iload*iloadf_emt) + x2_emt + +i_cap = -idc_emt - i_load + (1-duty_cycle_emt)*iL_emt + +p_capacitor_emt = vdc_emt*i_cap +p_bat_inductor = (sys.gfmi_e[0].v_s - (1-duty_cycle_emt)*vdc_emt)*iL_emt + +fig.add_trace(go.Scatter(x=tps, y=pbattery_emt, name="p_battery (emt)", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=np.multiply(pload_emt, -1.0), name="p_load (emt)", mode='lines', line=dict(color='blue', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=p_ac_emt, name="p_ac (emt)", mode='lines', line=dict(color='green', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='p (calculated)', row=r, col=c) + +power_sum = pload_emt - np.multiply(p_ac_emt, -1.0) + p_capacitor_emt +r, c = 13,2 +fig.add_trace(go.Scatter(x=tps, y=p_capacitor_emt, name="p_capacitor", mode='lines', line=dict(color='pink', dash='dash'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='p capacitor', row=r, col=c) + +r, c = 14,1 +fig.add_trace(go.Scatter(x=tps, y=p_bat_inductor, name="battery inductor power", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='p inductor', row=r, col=c) + +r, c = 14, 1 + +# p_sh_emt = np.multiply(i_bus_d_emt,v_sh_d_emt) + np.multiply(i_bus_q_emt,v_sh_q_emt) +# #ptracking = -0.1 -0.1*np.sin(2*np.pi*0.1*tps) + +# fig.add_trace(go.Scatter(x=tps, y=p_pc_emt, name="p_pc", mode='lines', line=dict(color='red', dash='solid'), legendgroup=str(r)), row=r, col=c) +# #fig.add_trace(go.Scatter(x=tps, y=p_sh_emt, name="p_actual", mode='lines', line=dict(color='blue', dash='dash'), legendgroup=str(r)), row=r, col=c) +# #fig.add_trace(go.Scatter(x=tps, y=ptracking, name="p_ref", mode='lines', line=dict(color='green', dash='dot'), legendgroup=str(r)), row=r, col=c) + +# fig.update_xaxes(title_text='Time [s]', row=r, col=c) +# fig.update_yaxes(title_text='p (calculated)', row=r, col=c) + +fig.update_layout(height=1200*4, + width=800*2, + legend_tracegroupgap=400, + margin={'t': 0, 'l': 0, 'b': 0, 'r': 0}) +fig.show() +fig.write_html("examples/small_signal_and_emt/2-bus-src-gfmi_e/ssm_emt_comparison.html") +print('ok') diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/ssm_analysis.py b/examples/small_signal_and_emt/2-bus-src-gfmi_e/ssm_analysis.py new file mode 100644 index 0000000..c6442b3 --- /dev/null +++ b/examples/small_signal_and_emt/2-bus-src-gfmi_e/ssm_analysis.py @@ -0,0 +1,129 @@ +""" + +Small signal analysis of GFMIE v INF source under variation in Pload, Pref, and Qref. + +""" + +# Import Python standard and third-party packages +from pathlib import Path +import numpy as np +import seaborn as sns +import matplotlib.pyplot as plt + +# Import sting package +from sting.system.core import System +from sting.system.operations import SystemModifier +from sting.modules.power_flow.core import ACPowerFlow +from sting.modules.small_signal_modeling.core import SmallSignalModel + +# Specify path of the case study directory +case_dir = Path(__file__).resolve().parent + +# Construct system and small-signal model + +inputs = {} +t_max = 2.0 + +# Load system from CSV files +sys = System.from_csv(case_directory=case_dir) + +# Define range of P and Q to vary over +n = 11 +Prange = np.linspace(100,0,n) +Qrange = np.linspace(-50,50,n) + +Sbase = 100 # MVA +vdc_ref = 1.05 # pu + +def run_sim(sys, P, Q, Sbase, vdc_ref, factor): + sys.gfmi_e[0].minimum_active_power_MW = -P*factor + sys.gfmi_e[0].maximum_active_power_MW = -P*factor + sys.gfmi_e[0].minimum_reactive_power_MVAR = Q + sys.gfmi_e[0].maximum_reactive_power_MVAR = Q + sys.gfmi_e[0].i_load_ref = P/Sbase/vdc_ref + + # Run power flow + pf = ACPowerFlow(system=sys, model_settings=None, solver_settings=None) + pf.solve() + + # Break down lines into branches and shunts for small-signal modeling + sys_modifier = SystemModifier(system=sys) + sys_modifier.decompose_lines() + sys_modifier.combine_shunts() + + # Construct small-signal model + ssm = SmallSignalModel(system=sys) + ssm.construct_system_ssm() + return ssm + +# Case 1: Pref = Pload +results = np.zeros([n,n]) +i = 0 +for P in Prange: + j = 0 + for Q in Qrange: + ssm = run_sim(sys, P, Q, Sbase, vdc_ref, 1.0) + + max_eig = np.max(np.linalg.eigvals(ssm.model.A).real) + + results[i,j] = max_eig + j += 1 + i += 1 + +# Plot results +fig, axes = plt.subplots(nrows=1,ncols=3, figsize=(30,10)) + +# Colorbar - use the same range for each +vmin = -6 +vmax = 0 +# Plot small-signal stability heatmap +sns.heatmap(results, xticklabels=Qrange, yticklabels=Prange, linewidth=0.5, ax=axes[1], vmin=vmin, vmax=vmax, cbar=False, cbar_kws = {'label': 'maximum eig. real part'}) +axes[1].set_xlabel("Q_sh (MVAR)") +axes[1].set_ylabel("P_load (MW)") +axes[1].set_title("Pref = Pload") + +## Case 2: Pref = 0.5*Pload +results = np.zeros([n,n]) +i = 0 +for P in Prange: + j = 0 + for Q in Qrange: + ssm = run_sim(sys, P, Q, Sbase, vdc_ref, 0.5) + + max_eig = np.max(np.linalg.eigvals(ssm.model.A).real) + + results[i,j] = max_eig + j += 1 + i += 1 + + +sns.heatmap(results, xticklabels=Qrange, yticklabels=Prange, linewidth=0.5, ax=axes[0], vmin=vmin, vmax=vmax, cbar=False, cbar_kws = {'label': 'maximum eig. real part'}) +axes[0].set_xlabel("Q_sh (MVAR)") +axes[0].set_ylabel("P_load (MW)") +axes[0].set_title("Pref = 0.5*Pload") + +## Case 3: Pref = 1.5*Pload +results = np.zeros([n,n]) +i = 0 +for P in Prange: + j = 0 + for Q in Qrange: + ssm = run_sim(sys, P, Q, Sbase, vdc_ref, 1.5) + + max_eig = np.max(np.linalg.eigvals(ssm.model.A).real) + + results[i,j] = max_eig + j += 1 + i += 1 + +sns.heatmap(results, xticklabels=Qrange, yticklabels=Prange, linewidth=0.5,ax=axes[2], vmin=vmin, vmax=vmax, cbar=True, cbar_kws = {'label': 'maximum eig. real part'}) +axes[2].set_xlabel("Q_sh (MVAR)") +axes[2].set_ylabel("P_load (MW)") +axes[2].set_title("Pref = 1.5*Pload") +fig.suptitle("Effect of Pref v Pload across P & Q space") + +plt.show() +plt.savefig(str(case_dir)+"/ssm_heatmaps.png") + +print('ok') + \ No newline at end of file diff --git a/examples/small_signal_and_emt/2-bus-src-gfmi_e/ssm_heatmaps.png b/examples/small_signal_and_emt/2-bus-src-gfmi_e/ssm_heatmaps.png new file mode 100644 index 0000000000000000000000000000000000000000..1df24922a5e364cd399881744a18f535990efc52 GIT binary patch literal 55762 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 h;Q#L@+4bj= 0.5 else 0.0 + +def step2(t): + return 0.0 + +def step3(t): + return 0.1 if t > 1.0 else 0.0 + +inputs = {'infinite_sources_0': {'v_ref_d': step1}, + 'gfmi_c_0': {'p_ref': step2, + 'q_ref': step2, + 'v_ref': step2, + 'v_dc_ref': step2, + 'v_s': step2, + 'i_load_ref': step2}} + +t_max = 2.0 + +# Load system from CSV files +sys = System.from_csv(case_directory=case_dir) + +n = 3 +Prange = np.linspace(100,0,n) +Qrange = np.linspace(-50,50,n) + +Sbase = 100 # MVA +vdc_ref = 1.05 # pu + +tps = np.linspace(0, t_max, 500) +dt = tps[1] - tps[0] + +def run_sim(sys, P, Q, Sbase, vdc_ref, factor): + sys.gfmi_c[0].minimum_active_power_MW = -P*factor + sys.gfmi_c[0].maximum_active_power_MW = -P*factor + sys.gfmi_c[0].minimum_reactive_power_MVAR = Q + sys.gfmi_c[0].maximum_reactive_power_MVAR = Q + + # Run power flow + pf = ACPowerFlow(system=sys, model_settings=None, solver_settings=None) + pf.solve() + + # Break down lines into branches and shunts for small-signal modeling + sys_modifier = SystemModifier(system=sys) + sys_modifier.decompose_lines() + sys_modifier.combine_shunts() + + # Construct small-signal model + ssm = SmallSignalModel(system=sys) + ssm.construct_system_ssm() + + emt_sc = SimulationEMT(system=sys) + emt_sc.sim(t_max, inputs) + return emt_sc + + +# Case 1: Pref = Pload +results_rocof = np.zeros([Prange.shape[0],Qrange.shape[0]]) +results_nadir = np.zeros([Prange.shape[0],Qrange.shape[0]]) + +i = 0 +for P in Prange: + j = 0 + for Q in Qrange: + emt_sc = run_sim(sys, P, Q, Sbase, vdc_ref, 1.0) + + # Measure some performance metrics - frequency ROCOF and nadir and steady state error ? + gfm = emt_sc.system.gfmi_c[0].variables_emt.x.value + w_pc = gfm[1,:] + # nadir + nadir = np.min(w_pc) + results_nadir[i,j] = nadir + # rocof - calculate as a moving average of duration 100ms (~25 timesteps for us) + df_dt = np.abs(np.diff(w_pc)/dt) # calculate raw rocof + df_dt_ma = np.convolve(df_dt,np.ones(25)/25) # get moving averages over 25 time steps (~100ms) + rocof = np.max(df_dt_ma) + + results_rocof[i,j] = rocof + j += 1 + i += 1 + +# Plot results +fig, axes = plt.subplots(nrows=2,ncols=3, figsize=(30,15)) + +sns.heatmap(results_nadir, xticklabels=Qrange, yticklabels=Prange, linewidth=0.5, ax=axes[0,1], cbar=True, cbar_kws = {'label': 'nadir'}) +axes[0,1].set_xlabel("Q_sh") +axes[0,1].set_ylabel("P_load") +axes[0,1].set_title("Pref = Pload") + +sns.heatmap(results_rocof, xticklabels=Qrange, yticklabels=Prange, linewidth=0.5, ax=axes[1,1], cbar=True, cbar_kws = {'label': 'rocof'}) +axes[1,1].set_xlabel("Q_sh") +axes[1,1].set_ylabel("P_load") +axes[1,1].set_title("Pref = Pload") + + +# Case 2: Pref < Pload (Pref=0.8*Pload) + +results_rocof = np.zeros([Prange.shape[0],Qrange.shape[0]]) +results_nadir = np.zeros([Prange.shape[0],Qrange.shape[0]]) + +i = 0 +for P in Prange: + j = 0 + for Q in Qrange: + emt_sc = run_sim(sys, P, Q, Sbase, vdc_ref, 0.8) + + # Measure some performance metrics - frequency ROCOF and nadir and steady state error ? + gfm = emt_sc.system.gfmi_c[0].variables_emt.x.value + w_pc = gfm[1,:] + # nadir + nadir = np.min(w_pc) + results_nadir[i,j] = nadir + # rocof - calculate as a moving average of duration 100ms (~25 timesteps for us) + df_dt = np.abs(np.diff(w_pc)/dt) # calculate raw rocof + df_dt_ma = np.convolve(df_dt,np.ones(25)/25) # get moving averages over 25 time steps (~100ms) + rocof = np.max(df_dt_ma) + + results_rocof[i,j] = rocof + j += 1 + i += 1 + +# Plot results + +sns.heatmap(results_nadir, xticklabels=Qrange, yticklabels=Prange, linewidth=0.5, ax=axes[0,0], cbar=True, cbar_kws = {'label': 'nadir'}) +axes[0,0].set_xlabel("Q_sh") +axes[0,0].set_ylabel("P_load") +axes[0,0].set_title("Pref = 0.8*Pload") + +sns.heatmap(results_rocof, xticklabels=Qrange, yticklabels=Prange, linewidth=0.5, ax=axes[1,0], cbar=True, cbar_kws = {'label': 'rocof'}) +axes[1,0].set_xlabel("Q_sh") +axes[1,0].set_ylabel("P_load") +axes[1,0].set_title("Pref = 0.8*Pload") + + +# Case 3: Pref > Pload (Pref=1.2*Pload) + +results_rocof = np.zeros([Prange.shape[0],Qrange.shape[0]]) +results_nadir = np.zeros([Prange.shape[0],Qrange.shape[0]]) + +i = 0 +for P in Prange: + j = 0 + for Q in Qrange: + emt_sc = run_sim(sys, P, Q, Sbase, vdc_ref, 1.2) + + # Measure some performance metrics - frequency ROCOF and nadir and steady state error ? + gfm = emt_sc.system.gfmi_c[0].variables_emt.x.value + w_pc = gfm[1,:] + # nadir + nadir = np.min(w_pc) + results_nadir[i,j] = nadir + # rocof - calculate as a moving average of duration 100ms (~25 timesteps for us) + df_dt = np.abs(np.diff(w_pc)/dt) # calculate raw rocof + df_dt_ma = np.convolve(df_dt,np.ones(25)/25) # get moving averages over 25 time steps (~100ms) + rocof = np.max(df_dt_ma) + + results_rocof[i,j] = rocof + j += 1 + i += 1 + +# Plot results + +sns.heatmap(results_nadir, xticklabels=Qrange, yticklabels=Prange, linewidth=0.5, ax=axes[0,2], cbar=True, cbar_kws = {'label': 'nadir'}) +axes[0,2].set_xlabel("Q_sh") +axes[0,2].set_ylabel("P_load") +axes[0,2].set_title("Pref = 1.2*Pload") + +sns.heatmap(results_rocof, xticklabels=Qrange, yticklabels=Prange, linewidth=0.5, ax=axes[1,2], cbar=True, cbar_kws = {'label': 'rocof'}) +axes[1,2].set_xlabel("Q_sh") +axes[1,2].set_ylabel("P_load") +axes[1,2].set_title("Pref = 1.2*Pload") + +plt.show() +plt.savefig(str(case_dir)+"/emt_heatmaps.png") + +print('ok') \ No newline at end of file diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/emt_heatmaps.png b/examples/small_signal_and_emt/2-bus_src-gfm/emt_heatmaps.png new file mode 100644 index 0000000000000000000000000000000000000000..72c694a9167ed5587a5e97a70e301eaaeea8c24d GIT binary patch literal 93334 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


X}yq`~7H1j3(W~w|9&QBpY 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
9R3FU^LX6fTTunvGQbS=rrM3qJMw&7fL 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 JYkvIYe*tdyO`8A! literal 0 HcmV?d00001 diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/inputs/buses.csv b/examples/small_signal_and_emt/2-bus_src-gfm/inputs/buses.csv index b50acd6..3817d3d 100644 --- a/examples/small_signal_and_emt/2-bus_src-gfm/inputs/buses.csv +++ b/examples/small_signal_and_emt/2-bus_src-gfm/inputs/buses.csv @@ -1,3 +1,3 @@ name,base_power_MVA,base_voltage_kV,base_frequency_Hz,minimum_voltage_pu,maximum_voltage_pu -lima,1.00E+02,2.30E+02,60,1,1 -santiago,1.00E+02,2.30E+02,60,0.95,1.3 \ No newline at end of file +lima,1.00E+02,2.30E+02,60,0.95,1.05 +santiago,1.00E+02,2.30E+02,60,0.95,1.05 \ No newline at end of file diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/inputs/gfmi_c.csv b/examples/small_signal_and_emt/2-bus_src-gfm/inputs/gfmi_c.csv index 3c5387f..8f66653 100755 --- a/examples/small_signal_and_emt/2-bus_src-gfm/inputs/gfmi_c.csv +++ b/examples/small_signal_and_emt/2-bus_src-gfm/inputs/gfmi_c.csv @@ -1,2 +1,2 @@ name,bus,minimum_active_power_MW,maximum_active_power_MW,minimum_reactive_power_MVAR,maximum_reactive_power_MVAR,base_power_MVA,base_voltage_kV,base_frequency_Hz,cost_variable_USDperMWh,rf1_pu,xf1_pu,rsh_pu,csh_pu,txr_power_MVA,txr_voltage1_kV,txr_voltage2_kV,txr_r1_pu,txr_x1_pu,txr_r2_pu,txr_x2_pu,h_s,kd_pu,droop_q_pu,tau_pc_s,v_dc_pu,kp_vc_pu,ki_vc_puHz -solar,santiago,80,80,50,51,1.00E+02,4.80E-01,60,0,0.02,0.1,1,0.1,1.00E+02,4.80E-01,2.30E+02,0.01,0.1,0.02,0.1,0.5,70,0,0.001,1,1,10 \ No newline at end of file +solar,santiago,-50,-50,-10,10,1.00E+02,4.80E-01,60,0,0.02,0.1,10,1,1.00E+02,4.80E-01,2.30E+02,0.01,0.1,0.02,0.1,0.5,70,0.01,0.001,1.05,1,10 \ No newline at end of file diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/active_power_balance_by_bus.csv b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/active_power_balance_by_bus.csv index e798b85..43499bd 100644 --- a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/active_power_balance_by_bus.csv +++ b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/active_power_balance_by_bus.csv @@ -1,3 +1,3 @@ bus,timepoint,generator_dispatch_MW,load_shedding_MW,load_MW,net_line_leaving_flow_MW -lima,timepoint_1,-67.08056522433783,-9.97494096311732e-9,0.0,-67.08056523417291 -santiago,timepoint_1,80.0,-9.974940965584796e-9,0.0,79.99999998990339 +lima,timepoint_1,60.31569213226618,-9.974940964403198e-9,0.0,60.31569212229119 +santiago,timepoint_1,-50.0,-9.974940964403193e-9,0.0,-50.00000000997488 diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/bus_voltage.csv b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/bus_voltage.csv index aa7960b..d17c3a2 100644 --- a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/bus_voltage.csv +++ b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/bus_voltage.csv @@ -1,3 +1,3 @@ id,bus,timepoint,voltage_magnitude_pu,voltage_angle_deg -0,lima,timepoint_1,1.0,0.0 -1,santiago,timepoint_1,1.2093116675812525,17.191975663648932 +0,lima,timepoint_1,1.0039676883731015,0.0 +1,santiago,timepoint_1,0.9966223958255749,-15.986449720491722 diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/costs_summary.csv b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/costs_summary.csv index 004cadd..22bb914 100644 --- a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/costs_summary.csv +++ b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/costs_summary.csv @@ -1,2 +1,2 @@ component,cost -total_cost_USD,-0.0000398997638476992 +total_cost_USD,-0.00003989976385761279 diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/generator_dispatch.csv b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/generator_dispatch.csv index 3cbe5a5..3ad6183 100644 --- a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/generator_dispatch.csv +++ b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/generator_dispatch.csv @@ -1,3 +1,3 @@ id,type,generator,timepoint,active_power_MW,reactive_power_MVAR -0,infinite_sources,gen1,timepoint_1,-67.08056522433783,-36.2809234833063 -0,gfmi_c,solar,timepoint_1,80.0,50.227752474633064 +0,infinite_sources,gen1,timepoint_1,60.31569213226618,1.388783529105015 +0,gfmi_c,solar,timepoint_1,-50.0,0.7526101226466527 diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/line_flows.csv b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/line_flows.csv index 365c6aa..6eac7b5 100644 --- a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/line_flows.csv +++ b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/line_flows.csv @@ -1,2 +1,2 @@ line,from_bus,to_bus,existing_capacity_MW,active_power_from_bus_MW,reactive_power_from_bus_MVAR,active_power_to_bus_MW,reactive_power_to_bus_MVAR,active_power_loss_MW,reactive_power_loss_MVAR -tx_1,lima,santiago,inf,-67.08056523417287,-36.28092349329843,79.99999998990337,50.22775246504935,12.919434755730506,13.946828971750918 +tx_1,lima,santiago,inf,60.31569212229122,1.3887835191300466,-50.00000000997491,0.7526101126717135,10.315692112316306,2.14139363180176 diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/load_shedding.csv b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/load_shedding.csv index 69b1b33..2061806 100644 --- a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/load_shedding.csv +++ b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/load_shedding.csv @@ -1,3 +1,3 @@ bus,timepoint,active_load_shedding_MW,reactive_load_shedding_MVAR -lima,timepoint_1,-9.97494096311732e-9,-9.974940964300128e-9 -santiago,timepoint_1,-9.974940965584796e-9,-9.974940954696962e-9 +lima,timepoint_1,-9.974940964403198e-9,-9.9749409644032e-9 +santiago,timepoint_1,-9.974940964403193e-9,-9.97494096440319e-9 diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/reactive_power_balance_by_bus.csv b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/reactive_power_balance_by_bus.csv index 6626494..1f256f2 100644 --- a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/reactive_power_balance_by_bus.csv +++ b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/reactive_power_balance_by_bus.csv @@ -1,3 +1,3 @@ bus,timepoint,generator_dispatch_MVAR,load_shedding_MVAR,load_MVAR,net_line_leaving_flow_MVAR -lima,timepoint_1,-36.2809234833063,-9.974940964300128e-9,0.0,-36.28092349329843 -santiago,timepoint_1,50.227752474633064,-9.974940954696962e-9,0.0,50.22775246504937 +lima,timepoint_1,1.388783529105015,-9.9749409644032e-9,0.0,1.3887835191300466 +santiago,timepoint_1,0.7526101226466527,-9.97494096440319e-9,0.0,0.7526101126717357 diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/solver_status.csv b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/solver_status.csv index 0f015d9..69f8c08 100644 --- a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/solver_status.csv +++ b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/ac_power_flow/solver_status.csv @@ -2,4 +2,4 @@ attribute,value solver_name,ipopt solver_status,ok termination_condition,optimal -time_spent_seconds,0.016715049743652344 +time_spent_seconds,0.0771188735961914 diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/component_connection_matrices/F.csv b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/component_connection_matrices/F.csv index a6b49a3..f3b6a13 100644 --- a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/component_connection_matrices/F.csv +++ b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/component_connection_matrices/F.csv @@ -1,4 +1,4 @@ -Index,"('infinite_sources_0', 'i_bus_D')","('infinite_sources_0', 'i_bus_Q')","('gfmi_c_0', 'i_bus_D')","('gfmi_c_0', 'i_bus_Q')","('pa_rc_0', 'v_bus_D')","('pa_rc_0', 'v_bus_Q')","('pa_rc_1', 'v_bus_D')","('pa_rc_1', 'v_bus_Q')","('se_rl_0', 'i_br_D')","('se_rl_0', 'i_br_Q')" +Index,"('infinite_sources_0', 'i_bus_D')","('infinite_sources_0', 'i_bus_Q')","('gfmi_c_0', 'i_bus_D')","('gfmi_c_0', 'i_bus_Q')","('shunt_parallel_rc_0', 'v_bus_D')","('shunt_parallel_rc_0', 'v_bus_Q')","('shunt_parallel_rc_1', 'v_bus_D')","('shunt_parallel_rc_1', 'v_bus_Q')","('branch_series_rl_0', 'i_br_D')","('branch_series_rl_0', 'i_br_Q')" "('infinite_sources_0', 'v_ref_d')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('infinite_sources_0', 'v_ref_q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('infinite_sources_0', 'v_bus_D')",0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0 @@ -8,11 +8,11 @@ Index,"('infinite_sources_0', 'i_bus_D')","('infinite_sources_0', 'i_bus_Q')","( "('gfmi_c_0', 'v_ref')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_c_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0 "('gfmi_c_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0 -"('pa_rc_0', 'i_bus_D')",1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-1.0,0.0 -"('pa_rc_0', 'i_bus_Q')",0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-1.0 -"('pa_rc_1', 'i_bus_D')",0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0 -"('pa_rc_1', 'i_bus_Q')",0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,1.0 -"('se_rl_0', 'v_from_bus_D')",0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'v_from_bus_Q')",0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'v_to_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0 -"('se_rl_0', 'v_to_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0 +"('shunt_parallel_rc_0', 'i_bus_D')",1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-1.0,0.0 +"('shunt_parallel_rc_0', 'i_bus_Q')",0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-1.0 +"('shunt_parallel_rc_1', 'i_bus_D')",0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0 +"('shunt_parallel_rc_1', 'i_bus_Q')",0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,1.0 +"('branch_series_rl_0', 'v_from_bus_D')",0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'v_from_bus_Q')",0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'v_to_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'v_to_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0 diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/component_connection_matrices/G.csv b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/component_connection_matrices/G.csv index 282ae29..703f4ab 100644 --- a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/component_connection_matrices/G.csv +++ b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/component_connection_matrices/G.csv @@ -8,11 +8,11 @@ Index,"('infinite_sources_0', 'v_ref_d')","('infinite_sources_0', 'v_ref_q')","( "('gfmi_c_0', 'v_ref')",0.0,0.0,0.0,0.0,1.0 "('gfmi_c_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0 "('gfmi_c_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'i_bus_D')",0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'i_bus_Q')",0.0,0.0,0.0,0.0,0.0 -"('pa_rc_1', 'i_bus_D')",0.0,0.0,0.0,0.0,0.0 -"('pa_rc_1', 'i_bus_Q')",0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'v_from_bus_D')",0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'v_from_bus_Q')",0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'v_to_bus_D')",0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'v_to_bus_Q')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'i_bus_D')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'i_bus_Q')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'i_bus_D')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'i_bus_Q')",0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'v_from_bus_D')",0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'v_from_bus_Q')",0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'v_to_bus_D')",0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'v_to_bus_Q')",0.0,0.0,0.0,0.0,0.0 diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/component_connection_matrices/H.csv b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/component_connection_matrices/H.csv index 05c50bf..8d8fa5a 100644 --- a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/component_connection_matrices/H.csv +++ b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/component_connection_matrices/H.csv @@ -1,11 +1,11 @@ -Index,"('infinite_sources_0', 'i_bus_D')","('infinite_sources_0', 'i_bus_Q')","('gfmi_c_0', 'i_bus_D')","('gfmi_c_0', 'i_bus_Q')","('pa_rc_0', 'v_bus_D')","('pa_rc_0', 'v_bus_Q')","('pa_rc_1', 'v_bus_D')","('pa_rc_1', 'v_bus_Q')","('se_rl_0', 'i_br_D')","('se_rl_0', 'i_br_Q')" +Index,"('infinite_sources_0', 'i_bus_D')","('infinite_sources_0', 'i_bus_Q')","('gfmi_c_0', 'i_bus_D')","('gfmi_c_0', 'i_bus_Q')","('shunt_parallel_rc_0', 'v_bus_D')","('shunt_parallel_rc_0', 'v_bus_Q')","('shunt_parallel_rc_1', 'v_bus_D')","('shunt_parallel_rc_1', 'v_bus_Q')","('branch_series_rl_0', 'i_br_D')","('branch_series_rl_0', 'i_br_Q')" "('infinite_sources_0', 'i_bus_D')",1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('infinite_sources_0', 'i_bus_Q')",0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_c_0', 'i_bus_D')",0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_c_0', 'i_bus_Q')",0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0 -"('pa_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0 -"('pa_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0 -"('se_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0 -"('se_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +"('shunt_parallel_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0 +"('branch_series_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0 +"('branch_series_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/component_connection_matrices/L.csv b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/component_connection_matrices/L.csv index 515e219..279f2e4 100644 --- a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/component_connection_matrices/L.csv +++ b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/component_connection_matrices/L.csv @@ -3,9 +3,9 @@ Index,"('infinite_sources_0', 'v_ref_d')","('infinite_sources_0', 'v_ref_q')","( "('infinite_sources_0', 'i_bus_Q')",0.0,0.0,0.0,0.0,0.0 "('gfmi_c_0', 'i_bus_D')",0.0,0.0,0.0,0.0,0.0 "('gfmi_c_0', 'i_bus_Q')",0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0 -"('pa_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0 -"('pa_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0 diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/A.csv b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/A.csv index 63dbe2e..813d915 100644 --- a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/A.csv +++ b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/A.csv @@ -1,20 +1,20 @@ -Index,"('infinite_sources_0', 'i_bus_d')","('infinite_sources_0', 'i_bus_q')","('gfmi_c_0', 'angle_pc')","('gfmi_c_0', 'w_pc')","('gfmi_c_0', 'p_pc')","('gfmi_c_0', 'q_pc')","('gfmi_c_0', 'pi_vc')","('gfmi_c_0', 'i_vsc_d')","('gfmi_c_0', 'i_vsc_q')","('gfmi_c_0', 'i_bus_d')","('gfmi_c_0', 'i_bus_q')","('gfmi_c_0', 'v_lcl_sh_d')","('gfmi_c_0', 'v_lcl_sh_q')","('pa_rc_0', 'v_bus_D')","('pa_rc_0', 'v_bus_Q')","('pa_rc_1', 'v_bus_D')","('pa_rc_1', 'v_bus_Q')","('se_rl_0', 'i_br_D')","('se_rl_0', 'i_br_Q')" -"('infinite_sources_0', 'i_bus_d')",-7.5398223686155035,376.99111843077515,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-697.9546674137151,285.21657689930515,0.0,0.0,0.0,0.0 -"('infinite_sources_0', 'i_bus_q')",-376.99111843077515,-7.5398223686155035,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-285.21657689930515,-697.9546674137151,0.0,0.0,0.0,0.0 +Index,"('infinite_sources_0', 'i_bus_d')","('infinite_sources_0', 'i_bus_q')","('gfmi_c_0', 'angle_pc')","('gfmi_c_0', 'w_pc')","('gfmi_c_0', 'p_pc')","('gfmi_c_0', 'q_pc')","('gfmi_c_0', 'pi_vc')","('gfmi_c_0', 'i_vsc_d')","('gfmi_c_0', 'i_vsc_q')","('gfmi_c_0', 'i_bus_d')","('gfmi_c_0', 'i_bus_q')","('gfmi_c_0', 'v_lcl_sh_d')","('gfmi_c_0', 'v_lcl_sh_q')","('shunt_parallel_rc_0', 'v_bus_D')","('shunt_parallel_rc_0', 'v_bus_Q')","('shunt_parallel_rc_1', 'v_bus_D')","('shunt_parallel_rc_1', 'v_bus_Q')","('branch_series_rl_0', 'i_br_D')","('branch_series_rl_0', 'i_br_Q')" +"('infinite_sources_0', 'i_bus_d')",-7.5398223686155035,376.99111843077515,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-723.1203801581415,-213.50908482472548,0.0,0.0,0.0,0.0 +"('infinite_sources_0', 'i_bus_q')",-376.99111843077515,-7.5398223686155035,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,213.50908482472548,-723.1203801581415,0.0,0.0,0.0,0.0 "('gfmi_c_0', 'angle_pc')",0.0,0.0,0.0,376.99111843077515,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfmi_c_0', 'w_pc')",0.0,0.0,0.0,-70.0,-1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_c_0', 'p_pc')",0.0,0.0,0.0,0.0,-1000.0,0.0,0.0,0.0,0.0,1305.929900975793,-175.63410139764756,552.3230020226116,-552.3353845084039,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_c_0', 'q_pc')",0.0,0.0,0.0,0.0,0.0,-1000.0,0.0,0.0,0.0,-175.63410139764756,-1305.929900975793,552.3353845084039,552.3230020226116,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_c_0', 'pi_vc')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-9.9107712566067,1.3328965073172159,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_c_0', 'i_vsc_d')",0.0,0.0,0.0,-225.20563327909315,0.0,0.0,3769.9111843077517,-75.39822368615502,376.99111843077515,0.0,0.0,-7506.183924847491,502.4901450459911,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_c_0', 'i_vsc_q')",0.0,0.0,0.0,-707.1660898606517,0.0,0.0,0.0,-376.99111843077515,-75.39822368615502,0.0,0.0,0.0,-3769.9111843077517,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_c_0', 'i_bus_d')",0.0,0.0,508.04951771675695,-208.22553435471542,0.0,0.0,0.0,0.0,0.0,-56.54866776461627,376.99111843077515,1884.9555921538758,0.0,0.0,0.0,-1631.2653040736207,-944.4739764110853,0.0,0.0 -"('gfmi_c_0', 'i_bus_q')",0.0,0.0,2222.161205510431,-208.22086626754765,0.0,0.0,0.0,0.0,0.0,-376.99111843077515,-56.54866776461627,0.0,1884.9555921538758,0.0,0.0,944.4739764110853,-1631.2653040736207,0.0,0.0 -"('gfmi_c_0', 'v_lcl_sh_d')",0.0,0.0,0.0,-66.21249632048333,0.0,0.0,0.0,3769.9111843077517,0.0,-3769.9111843077517,0.0,-3769.9111843077517,376.99111843077515,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_c_0', 'v_lcl_sh_q')",0.0,0.0,0.0,-492.3239739610557,0.0,0.0,0.0,0.0,3769.9111843077517,0.0,-3769.9111843077517,-376.99111843077515,-3769.9111843077517,0.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'v_bus_D')",5234.6599794295635,2139.124316049167,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-282.7433374093647,376.99111843077515,0.0,0.0,-5654.8667481872935,0.0 -"('pa_rc_0', 'v_bus_Q')",-2139.124316049167,5234.6599794295635,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-376.99111843077515,-282.7433374093647,0.0,0.0,0.0,-5654.8667481872935 -"('pa_rc_1', 'v_bus_D')",0.0,0.0,1138.0525352410905,0.0,0.0,0.0,0.0,0.0,0.0,4893.795887751882,-2833.421915066146,0.0,0.0,0.0,0.0,-282.7433374093647,376.99111843077515,5654.8667481872935,0.0 -"('pa_rc_1', 'v_bus_Q')",0.0,0.0,4267.955218941629,0.0,0.0,0.0,0.0,0.0,0.0,2833.421915066146,4893.795887751882,0.0,0.0,0.0,0.0,-376.99111843077515,-282.7433374093647,0.0,5654.8667481872935 -"('se_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,753.9822368615503,0.0,-753.9822368615503,0.0,-7.5398223686155035,376.99111843077515 -"('se_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,753.9822368615503,0.0,-753.9822368615503,-376.99111843077515,-7.5398223686155035 +"('gfmi_c_0', 'p_pc')",0.0,0.0,0.0,0.0,-1000.0,0.0,0.0,0.0,0.0,987.9260565411992,23.78030884341824,-496.76780316078685,-70.54199784602056,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_c_0', 'q_pc')",0.0,0.0,0.0,0.0,0.0,-1000.0,0.0,0.0,0.0,23.78030884341824,-987.9260565411992,70.54199784602056,-496.76780316078685,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_c_0', 'pi_vc')",0.0,0.0,0.0,0.0,0.0,-0.1,0.0,0.0,0.0,0.0,0.0,-9.997104207562575,-0.24063969567519944,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_c_0', 'i_vsc_d')",0.0,0.0,0.0,346.7421388408102,0.0,-37.69911184307752,3769.9111843077517,-75.39822368615502,376.99111843077515,0.0,0.0,-7538.730680585775,-90.71902801143482,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_c_0', 'i_vsc_q')",0.0,0.0,0.0,158.9980800432565,0.0,0.0,0.0,-376.99111843077515,-75.39822368615502,0.0,0.0,0.0,-3769.9111843077517,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_c_0', 'i_bus_d')",0.0,0.0,-236.09093185117854,-26.593706664312624,0.0,0.0,0.0,0.0,0.0,-56.54866776461627,376.99111843077515,1884.9555921538758,0.0,0.0,0.0,-1732.449388861673,742.7494190000986,0.0,0.0 +"('gfmi_c_0', 'i_bus_q')",0.0,0.0,1863.6945957046444,187.27704971398418,0.0,0.0,0.0,0.0,0.0,-376.99111843077515,-56.54866776461627,0.0,1884.9555921538758,0.0,0.0,-742.7494190000986,-1732.449388861673,0.0,0.0 +"('gfmi_c_0', 'v_lcl_sh_d')",0.0,0.0,0.0,8.964965227509495,0.0,0.0,0.0,376.99111843077515,0.0,-376.99111843077515,0.0,-37.69911184307752,376.99111843077515,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_c_0', 'v_lcl_sh_q')",0.0,0.0,0.0,-372.4393489823719,0.0,0.0,0.0,0.0,376.99111843077515,0.0,-376.99111843077515,-376.99111843077515,-37.69911184307752,0.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_D')",5423.402824069048,-1601.3181281788504,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-282.7433374093647,376.99111843077515,0.0,0.0,-5654.8667481872935,0.0 +"('shunt_parallel_rc_0', 'v_bus_Q')",1601.3181281788504,5423.402824069048,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-376.99111843077515,-282.7433374093647,0.0,0.0,0.0,-5654.8667481872935 +"('shunt_parallel_rc_1', 'v_bus_D')",0.0,0.0,-740.2906646531766,0.0,0.0,0.0,0.0,0.0,0.0,5197.348140598278,2228.2482458590544,0.0,0.0,0.0,0.0,-282.7433374093647,376.99111843077515,5654.8667481872935,0.0 +"('shunt_parallel_rc_1', 'v_bus_Q')",0.0,0.0,-2739.060301026596,0.0,0.0,0.0,0.0,0.0,0.0,-2228.2482458590544,5197.348140598278,0.0,0.0,0.0,0.0,-376.99111843077515,-282.7433374093647,0.0,5654.8667481872935 +"('branch_series_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,753.9822368615503,0.0,-753.9822368615503,0.0,-7.5398223686155035,376.99111843077515 +"('branch_series_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,753.9822368615503,0.0,-753.9822368615503,-376.99111843077515,-7.5398223686155035 diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/B.csv b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/B.csv index fa9e8a8..4e32179 100644 --- a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/B.csv +++ b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/B.csv @@ -5,16 +5,16 @@ Index,"('infinite_sources_0', 'v_ref_d')","('infinite_sources_0', 'v_ref_q')","( "('gfmi_c_0', 'w_pc')",0.0,0.0,1.0,0.0,0.0 "('gfmi_c_0', 'p_pc')",0.0,0.0,0.0,0.0,0.0 "('gfmi_c_0', 'q_pc')",0.0,0.0,0.0,0.0,0.0 -"('gfmi_c_0', 'pi_vc')",0.0,0.0,0.0,0.0,10.0 -"('gfmi_c_0', 'i_vsc_d')",0.0,0.0,0.0,0.0,3769.9111843077517 +"('gfmi_c_0', 'pi_vc')",0.0,0.0,0.0,0.1,10.0 +"('gfmi_c_0', 'i_vsc_d')",0.0,0.0,0.0,37.69911184307752,3769.9111843077517 "('gfmi_c_0', 'i_vsc_q')",0.0,0.0,0.0,0.0,0.0 "('gfmi_c_0', 'i_bus_d')",0.0,0.0,0.0,0.0,0.0 "('gfmi_c_0', 'i_bus_q')",0.0,0.0,0.0,0.0,0.0 "('gfmi_c_0', 'v_lcl_sh_d')",0.0,0.0,0.0,0.0,0.0 "('gfmi_c_0', 'v_lcl_sh_q')",0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0 -"('pa_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0 -"('pa_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0 diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/C.csv b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/C.csv index 424533a..27e8754 100644 --- a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/C.csv +++ b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/C.csv @@ -1,11 +1,11 @@ -Index,"('infinite_sources_0', 'i_bus_d')","('infinite_sources_0', 'i_bus_q')","('gfmi_c_0', 'angle_pc')","('gfmi_c_0', 'w_pc')","('gfmi_c_0', 'p_pc')","('gfmi_c_0', 'q_pc')","('gfmi_c_0', 'pi_vc')","('gfmi_c_0', 'i_vsc_d')","('gfmi_c_0', 'i_vsc_q')","('gfmi_c_0', 'i_bus_d')","('gfmi_c_0', 'i_bus_q')","('gfmi_c_0', 'v_lcl_sh_d')","('gfmi_c_0', 'v_lcl_sh_q')","('pa_rc_0', 'v_bus_D')","('pa_rc_0', 'v_bus_Q')","('pa_rc_1', 'v_bus_D')","('pa_rc_1', 'v_bus_Q')","('se_rl_0', 'i_br_D')","('se_rl_0', 'i_br_Q')" -"('infinite_sources_0', 'i_bus_D')",0.9256911281079382,0.3782802338772842,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('infinite_sources_0', 'i_bus_Q')",-0.3782802338772842,0.9256911281079382,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_c_0', 'i_bus_D')",0.0,0.0,0.20125187487501822,0.0,0.0,0.0,0.0,0.0,0.0,0.8654131221254014,-0.5010590065582746,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfmi_c_0', 'i_bus_Q')",0.0,0.0,0.7547401926508261,0.0,0.0,0.0,0.0,0.0,0.0,0.5010590065582746,0.8654131221254014,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0 -"('pa_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0 -"('pa_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0 -"('se_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0 -"('se_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +Index,"('infinite_sources_0', 'i_bus_d')","('infinite_sources_0', 'i_bus_q')","('gfmi_c_0', 'angle_pc')","('gfmi_c_0', 'w_pc')","('gfmi_c_0', 'p_pc')","('gfmi_c_0', 'q_pc')","('gfmi_c_0', 'pi_vc')","('gfmi_c_0', 'i_vsc_d')","('gfmi_c_0', 'i_vsc_q')","('gfmi_c_0', 'i_bus_d')","('gfmi_c_0', 'i_bus_q')","('gfmi_c_0', 'v_lcl_sh_d')","('gfmi_c_0', 'v_lcl_sh_q')","('shunt_parallel_rc_0', 'v_bus_D')","('shunt_parallel_rc_0', 'v_bus_Q')","('shunt_parallel_rc_1', 'v_bus_D')","('shunt_parallel_rc_1', 'v_bus_Q')","('branch_series_rl_0', 'i_br_D')","('branch_series_rl_0', 'i_br_Q')" +"('infinite_sources_0', 'i_bus_D')",0.9590681912721563,-0.2831752187073487,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('infinite_sources_0', 'i_bus_Q')",0.2831752187073487,0.9590681912721563,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_c_0', 'i_bus_D')",0.0,0.0,-0.1309121324371581,0.0,0.0,0.0,0.0,0.0,0.0,0.9190929463128948,0.3940408050416634,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_c_0', 'i_bus_Q')",0.0,0.0,-0.484372209460925,0.0,0.0,0.0,0.0,0.0,0.0,-0.3940408050416634,0.9190929463128948,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0 +"('branch_series_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0 +"('branch_series_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/D.csv b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/D.csv index 515e219..279f2e4 100644 --- a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/D.csv +++ b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/D.csv @@ -3,9 +3,9 @@ Index,"('infinite_sources_0', 'v_ref_d')","('infinite_sources_0', 'v_ref_q')","( "('infinite_sources_0', 'i_bus_Q')",0.0,0.0,0.0,0.0,0.0 "('gfmi_c_0', 'i_bus_D')",0.0,0.0,0.0,0.0,0.0 "('gfmi_c_0', 'i_bus_Q')",0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0 -"('pa_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0 -"('pa_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0 -"('pa_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0 -"('se_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0 +"('shunt_parallel_rc_1', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'i_br_D')",0.0,0.0,0.0,0.0,0.0 +"('branch_series_rl_0', 'i_br_Q')",0.0,0.0,0.0,0.0,0.0 diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/u.csv b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/u.csv index e97dff3..0da5867 100644 --- a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/u.csv +++ b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/u.csv @@ -1,6 +1,6 @@ name,component,type,init -v_ref_d,infinite_sources_0,device,0.8770607186443364 -v_ref_q,infinite_sources_0,device,-6.183078103210549e-18 -p_ref,gfmi_c_0,device,0.8183040522662995 -q_ref,gfmi_c_0,device,0.624304539854994 -v_ref,gfmi_c_0,device,1.3176874606052849 +v_ref_d,infinite_sources_0,device,1.0602915467925695 +v_ref_q,infinite_sources_0,device,-6.184065849485258e-17 +p_ref,gfmi_c_0,device,-0.4924473672884809 +q_ref,gfmi_c_0,device,0.05787698596992697 +v_ref,gfmi_c_0,device,0.9882122222891866 diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/x.csv b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/x.csv index 85dac69..0abab9f 100644 --- a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/x.csv +++ b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/x.csv @@ -1,20 +1,20 @@ name,component,type,init -i_bus_d,infinite_sources_0,"",-0.7582024031718437 -i_bus_q,infinite_sources_0,"",0.08209677086376665 +i_bus_d,infinite_sources_0,"",0.5722653561902081 +i_bus_q,infinite_sources_0,"",-0.18339083649397844 angle_pc,gfmi_c_0,"",0.0 w_pc,gfmi_c_0,"",0.0 -p_pc,gfmi_c_0,"",0.8183040522662995 -q_pc,gfmi_c_0,"",0.624304539854994 -pi_vc,gfmi_c_0,"",1.4031838768194038 -i_vsc_d,gfmi_c_0,"",1.8758163131381695 -i_vsc_q,gfmi_c_0,"",-0.5973764958084721 -i_bus_d,gfmi_c_0,"",0.5523230020226116 -i_bus_q,gfmi_c_0,"",-0.5523353845084039 -v_lcl_sh_d,gfmi_c_0,"",1.3059299009757932 -v_lcl_sh_q,gfmi_c_0,"",-0.17563410139764757 -v_bus_D,pa_rc_0,"",1.0 -v_bus_Q,pa_rc_0,"",0.0 -v_bus_D,pa_rc_1,"",1.1552793404899095 -v_bus_Q,pa_rc_1,"",0.3574414004915346 -i_br_D,se_rl_0,"",-0.7208056523417289 -i_br_Q,se_rl_0,"",0.2961425679329845 +p_pc,gfmi_c_0,"",-0.4924473672884809 +q_pc,gfmi_c_0,"",0.05787698596992697 +pi_vc,gfmi_c_0,"",0.8875147374562453 +i_vsc_d,gfmi_c_0,"",-0.42175550635008513 +i_vsc_q,gfmi_c_0,"",0.9197620895795204 +i_bus_d,gfmi_c_0,"",-0.49676780316078684 +i_bus_q,gfmi_c_0,"",-0.07054199784602057 +v_lcl_sh_d,gfmi_c_0,"",0.9879260565411991 +v_lcl_sh_q,gfmi_c_0,"",0.02378030884341824 +v_bus_D,shunt_parallel_rc_0,"",1.0039676883731015 +v_bus_Q,shunt_parallel_rc_0,"",0.0 +v_bus_D,shunt_parallel_rc_1,"",0.9580798748577896 +v_bus_Q,shunt_parallel_rc_1,"",-0.2744797866029319 +i_br_D,branch_series_rl_0,"",0.5505748558041546 +i_br_Q,branch_series_rl_0,"",-0.08076412991454072 diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/y.csv b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/y.csv index f441917..97bddd7 100644 --- a/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/y.csv +++ b/examples/small_signal_and_emt/2-bus_src-gfm/outputs/small_signal_model/y.csv @@ -1,11 +1,11 @@ name,component,type,init -i_bus_D,infinite_sources_0,"",-0.6708056522433783 -i_bus_Q,infinite_sources_0,"",0.36280923483306304 -i_bus_D,gfmi_c_0,"",0.7547401926508261 -i_bus_Q,gfmi_c_0,"",-0.2012518748750182 -v_bus_D,pa_rc_0,"",1.0 -v_bus_Q,pa_rc_0,"",0.0 -v_bus_D,pa_rc_1,"",1.1552793404899095 -v_bus_Q,pa_rc_1,"",0.3574414004915346 -i_br_D,se_rl_0,"",-0.7208056523417289 -i_br_Q,se_rl_0,"",0.2961425679329845 +i_bus_D,infinite_sources_0,"",0.6007732403221651 +i_bus_Q,infinite_sources_0,"",-0.013832950454366671 +i_bus_D,gfmi_c_0,"",-0.484372209460925 +i_bus_Q,gfmi_c_0,"",0.1309121324371581 +v_bus_D,shunt_parallel_rc_0,"",1.0039676883731015 +v_bus_Q,shunt_parallel_rc_0,"",0.0 +v_bus_D,shunt_parallel_rc_1,"",0.9580798748577896 +v_bus_Q,shunt_parallel_rc_1,"",-0.2744797866029319 +i_br_D,branch_series_rl_0,"",0.5505748558041546 +i_br_Q,branch_series_rl_0,"",-0.08076412991454072 diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/run.py b/examples/small_signal_and_emt/2-bus_src-gfm/run.py index bc4a638..5cb7e36 100644 --- a/examples/small_signal_and_emt/2-bus_src-gfm/run.py +++ b/examples/small_signal_and_emt/2-bus_src-gfm/run.py @@ -46,12 +46,12 @@ def step2(t): 'v_ref_d': step2 }, 'gfmi_c_0': { - 'p_ref': step1} + 'p_ref': step2} } t_max = 2.0 # Simulation length # Construct system and small-signal model -_, ssm = main.run_ssm(case_directory=case_dir) +sys, ssm = main.run_ssm(case_directory=case_dir) ssm.simulate_ssm(t_max=t_max, inputs=inputs) # Run EMT simulation main.run_emt(case_directory=case_dir, inputs=inputs, t_max=t_max) diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/ssm_analysis.py b/examples/small_signal_and_emt/2-bus_src-gfm/ssm_analysis.py new file mode 100644 index 0000000..2a08991 --- /dev/null +++ b/examples/small_signal_and_emt/2-bus_src-gfm/ssm_analysis.py @@ -0,0 +1,157 @@ +""" + +Small signal analysis of GFMI_E v INF source under variation in Pload, Pref, and Qref. + +""" + +# Import Python standard and third-party packages +from pathlib import Path +import numpy as np +import seaborn as sns +import matplotlib.pyplot as plt + +# Import sting package +from sting.system.core import System +from sting.system.operations import SystemModifier +from sting.modules.power_flow.core import ACPowerFlow +from sting.modules.small_signal_modeling.core import SmallSignalModel + +# Specify path of the case study directory +case_dir = Path(__file__).resolve().parent + +# Construct system and small-signal model + +inputs = {} +t_max = 2.0 + +# Load system from CSV files +sys = System.from_csv(case_directory=case_dir) + + +# Define range of P and Q to vary over +n = 11 +Prange = np.linspace(-100,0,n) +Qrange = Prange + +Sbase = 100 # MVA +vdc_ref = 1.05 # pu + +# Case 1: Pref = Pload +results = np.zeros([n,n]) +i = 0 +for P in Prange: + j = 0 + for Q in Qrange: + sys.gfmi_c[0].minimum_active_power_MW = P + sys.gfmi_c[0].maximum_active_power_MW = P + sys.gfmi_c[0].minimum_reactive_power_MVAR = Q + sys.gfmi_c[0].maximum_reactive_power_MVAR = Q + + # Run power flow + pf = ACPowerFlow(system=sys, model_settings=None, solver_settings=None) + pf.solve() + + # Break down lines into branches and shunts for small-signal modeling + sys_modifier = SystemModifier(system=sys) + sys_modifier.decompose_lines() + sys_modifier.combine_shunts() + + # Construct small-signal model + ssm = SmallSignalModel(system=sys) + ssm.construct_system_ssm() + + max_eig = np.max(np.linalg.eigvals(ssm.model.A).real) + + results[i,j] = max_eig + j += 1 + i += 1 + +# Plot results +fig, axes = plt.subplots(nrows=1,ncols=3, figsize=(30,10)) + +# Colorbar - use the same range for each +vmin = -6 +vmax = 0 +# Plot small-signal stability heatmap +sns.heatmap(results, xticklabels=Qrange, yticklabels=Prange, linewidth=0.5, ax=axes[1], vmin=vmin, vmax=vmax, cbar=False, cbar_kws = {'label': 'maximum eig. real part'}) +axes[1].set_xlabel("Q_sh (MVAR)") +axes[1].set_ylabel("P_load (MW)") +axes[1].set_title("Pref = Pload") + +## Case 2: Pref = 0.5*Pload +results = np.zeros([n,n]) +i = 0 +for P in Prange: + j = 0 + for Q in Qrange: + sys.gfmi_c[0].minimum_active_power_MW = P/2 + sys.gfmi_c[0].maximum_active_power_MW = P/2 + sys.gfmi_c[0].minimum_reactive_power_MVAR = Q + sys.gfmi_c[0].maximum_reactive_power_MVAR = Q + + # Run power flow + pf = ACPowerFlow(system=sys, model_settings=None, solver_settings=None) + pf.solve() + + # Break down lines into branches and shunts for small-signal modeling + sys_modifier = SystemModifier(system=sys) + sys_modifier.decompose_lines() + sys_modifier.combine_shunts() + + # Construct small-signal model + ssm = SmallSignalModel(system=sys) + ssm.construct_system_ssm() + + max_eig = np.max(np.linalg.eigvals(ssm.model.A).real) + + results[i,j] = max_eig + j += 1 + i += 1 + + +sns.heatmap(results, xticklabels=Qrange, yticklabels=Prange, linewidth=0.5, ax=axes[0], vmin=vmin, vmax=vmax, cbar=False, cbar_kws = {'label': 'maximum eig. real part'}) +axes[0].set_xlabel("Q_sh (MVAR)") +axes[0].set_ylabel("P_load (MW)") +axes[0].set_title("Pref = 0.5*Pload") + +## Case 3: Pref = 1.5*Pload +results = np.zeros([n,n]) +i = 0 +for P in Prange: + j = 0 + for Q in Qrange: + sys.gfmi_c[0].minimum_active_power_MW = P*1.5 + sys.gfmi_c[0].maximum_active_power_MW = P*1.5 + sys.gfmi_c[0].minimum_reactive_power_MVAR = Q + sys.gfmi_c[0].maximum_reactive_power_MVAR = Q + + # Run power flow + pf = ACPowerFlow(system=sys, model_settings=None, solver_settings=None) + pf.solve() + + # Break down lines into branches and shunts for small-signal modeling + sys_modifier = SystemModifier(system=sys) + sys_modifier.decompose_lines() + sys_modifier.combine_shunts() + + # Construct small-signal model + ssm = SmallSignalModel(system=sys) + ssm.construct_system_ssm() + + max_eig = np.max(np.linalg.eigvals(ssm.model.A).real) + + results[i,j] = max_eig + j += 1 + i += 1 + +sns.heatmap(results, xticklabels=Qrange, yticklabels=Prange, linewidth=0.5,ax=axes[2], vmin=vmin, vmax=vmax, cbar=True, cbar_kws = {'label': 'maximum eig. real part'}) +axes[2].set_xlabel("Q_sh (MVAR)") +axes[2].set_ylabel("P_load (MW)") +axes[2].set_title("Pref = 1.5*Pload") +fig.suptitle("Effect of Pref v Pload across P & Q space") + +plt.show() +plt.savefig(str(case_dir)+"/ssm_heatmaps.png") + +print('ok') + \ No newline at end of file diff --git a/examples/small_signal_and_emt/2-bus_src-gfm/ssm_heatmaps.png b/examples/small_signal_and_emt/2-bus_src-gfm/ssm_heatmaps.png new file mode 100644 index 0000000000000000000000000000000000000000..1df24922a5e364cd399881744a18f535990efc52 GIT binary patch literal 55762 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 h;Q#L@+4bj= 0.5 else 0.0 + +def step2(t): + return 0.0 + +inputs = { + 'infinite_sources_0': { + 'v_ref_d': step2 + } + } + +t_max = 2.0 # Simulation length (in seconds) + +# Specify path of the case study directory +case_dir = Path(__file__).resolve().parent + +# Construct system and small-signal model +sys = System.from_csv(case_directory=case_dir) + +# Construct system and small-signal model +_, ssm = main.run_ssm(case_directory=case_dir) +ssm.simulate_ssm(t_max=t_max, inputs=inputs) + +print('\nok') \ No newline at end of file diff --git a/examples/small_signal_and_emt/gfmi_e_v_gfmi_c.py b/examples/small_signal_and_emt/gfmi_e_v_gfmi_c.py new file mode 100644 index 0000000..8f5cb0d --- /dev/null +++ b/examples/small_signal_and_emt/gfmi_e_v_gfmi_c.py @@ -0,0 +1,275 @@ +""" +Compares the EMT and small signal response of the GFMI_C, which does not model the DC side of the converter, +the GFMI_E which models a battery and current-source load on the DC side. + +In progress - March 31 - Ruth +""" + +# Import Python standard and third-party packages +from pathlib import Path +import os +import numpy as np +import pandas as pd +import plotly.graph_objects as go +from plotly.subplots import make_subplots +from scipy.linalg import eig, inv +import seaborn as sns +import matplotlib.pyplot as plt +from sting.utils.transformations import dq02abc, abc2dq0 +from scipy import signal + + +# Import sting package +from sting import main +from sting.system.core import System + +# Specify path of the case study directory + +case_dir_gfmc = os.path.join(Path(__file__).resolve().parent,"2-bus_src-gfm") +case_dir_gfme = os.path.join(Path(__file__).resolve().parent,"2-bus-src-gfmi_e") + +# Define inputs +def step1(t): + return 0.3 if t >= 0.5 else 0.0 + +def step2(t): + return 0.0 + +# Combine inputs for gfmi_c and gfmi_e +inputs = {'infinite_sources_0': {'v_ref_d': step1}, + 'gfmi_e_0': {'p_ref': step2, + 'q_ref': step2, + 'v_ref': step2, + 'v_dc_ref': step2, + 'v_s': step2, + 'i_load_ref': step2}, + 'gfmi_c_0': {'p_ref': step2, + 'q_ref': step2, + 'v_ref': step2}} + +t_max = 2.0 + +# Run GFMI_C +_, ssm_c = main.run_ssm(case_directory=case_dir_gfmc) # Construct system and small-signal model +ssm_c.simulate_ssm(t_max=t_max, inputs=inputs) +sys_c, emt_sc_c = main.run_emt(case_directory=case_dir_gfmc, inputs=inputs, t_max=t_max) # Run EMT simulation + +# Run GFMI_E +_, ssm_e = main.run_ssm(case_directory=case_dir_gfme) # Construct system and small-signal model +ssm_e.simulate_ssm(t_max=t_max, inputs=inputs) +sys_e, emt_sc_e = main.run_emt(case_directory=case_dir_gfme, inputs=inputs, t_max=t_max) # Run EMT simulation + + +# # Compare eigenvalues of A matrix +# gfmic_A = pd.read_csv(case_dir_gfmc+"/outputs/small_signal_model/A.csv") +# gfmie_A = pd.read_csv(case_dir_gfme+"/outputs/small_signal_model/A.csv") + +# gfmie_eigs = np.linalg.eigvals(gfmie_A.iloc[:,1:].to_numpy()) +# gfmic_eigs = np.linalg.eigvals(gfmic_A.iloc[:,1:].to_numpy()) + +# # Plot eigenvalues +# fig = make_subplots( +# rows=1, cols=1, +# horizontal_spacing=0.15, +# vertical_spacing=0.05, +# ) + +# fig.add_trace(go.Scatter(x=gfmie_eigs.real, y=gfmie_eigs.imag, name="GFMI_E", mode="markers", marker=dict(size=12, opacity=1.0, symbol="circle", line=dict(color="black", width=1)))) +# fig.add_trace(go.Scatter(x=gfmic_eigs.real, y=gfmic_eigs.imag, name="GFMI_C", mode="markers", marker=dict(size=12, opacity=0.5, symbol="square", line=dict(color="black", width=1)))) +# fig.show() +# fig.write_html("examples/small_signal_and_emt/2-bus-scr-gfm_comparison/eig_comparison.html") + +# Compare EMT traces +gfmi_c = pd.read_csv(case_dir_gfmc+"/outputs/simulation_emt/gfmi_c_0_states.csv") +gfmi_e = pd.read_csv(case_dir_gfme+"/outputs/simulation_emt/gfmi_e_0_states.csv") + +fig = make_subplots( + rows=9, cols=2, + horizontal_spacing=0.15, + vertical_spacing=0.05, +) + +tps = gfmi_c["time"] + +# converting abc to dq +# GFMI_E +i_bus_de, i_bus_qe, _ = zip(*[abc2dq0(a, b, c, ang) for a, b, c, ang in zip(gfmi_e["i_bus_a"], gfmi_e["i_bus_b"], gfmi_e["i_bus_c"], gfmi_e["angle_pc"])]) +i_vsc_de, i_vsc_qe, _ = zip(*[abc2dq0(a, b, c, ang) for a, b, c, ang in zip(gfmi_e["i_vsc_a"], gfmi_e["i_vsc_b"], gfmi_e["i_vsc_c"], gfmi_e["angle_pc"])]) +v_sh_de, v_sh_qe, _ = zip(*[abc2dq0(a, b, c, ang) for a, b, c, ang in zip(gfmi_e["v_sh_a"], gfmi_e["v_sh_b"], gfmi_e["v_sh_c"], gfmi_e["angle_pc"])]) + +# GFMI_c +i_bus_dc, i_bus_qc, _ = zip(*[abc2dq0(a, b, c, ang) for a, b, c, ang in zip(gfmi_c["i_bus_a"], gfmi_c["i_bus_b"], gfmi_c["i_bus_c"], gfmi_c["angle_pc"])]) +i_vsc_dc, i_vsc_qc, _ = zip(*[abc2dq0(a, b, c, ang) for a, b, c, ang in zip(gfmi_c["i_vsc_a"], gfmi_c["i_vsc_b"], gfmi_c["i_vsc_c"], gfmi_c["angle_pc"])]) +v_sh_dc, v_sh_qc, _ = zip(*[abc2dq0(a, b, c, ang) for a, b, c, ang in zip(gfmi_c["v_sh_a"], gfmi_c["v_sh_b"], gfmi_c["v_sh_c"], gfmi_c["angle_pc"])]) + +r, c = 1,1 +fig.add_trace(go.Scatter(x=tps, y=gfmi_c["angle_pc"], name="GFMI_C", mode='lines', line=dict(color='red', dash='solid'), legendgroup='1'), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=gfmi_e["angle_pc"], name="GFMI_E", mode='lines', line=dict(color='blue', dash='dot'), legendgroup='1'), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='angle_pc', row=r, col=c) + +r, c = 1,2 +fig.add_trace(go.Scatter(x=tps, y=gfmi_c["w_pc"], name="GFMI_C", mode='lines', line=dict(color='red', dash='solid'), legendgroup='1'), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=gfmi_e["w_pc"], name="GFMI_E", mode='lines', line=dict(color='blue', dash='dot'), legendgroup='1'), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='w_pc', row=r, col=c) + +r, c = 2,1 +fig.add_trace(go.Scatter(x=tps, y=gfmi_c["p_pc"], name="GFMI_C", mode='lines', line=dict(color='red', dash='solid'), legendgroup='1'), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=gfmi_e["p_pc"], name="GFMI_E", mode='lines', line=dict(color='blue', dash='dot'), legendgroup='1'), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='p_pc', row=r, col=c) + +r, c = 2,2 +fig.add_trace(go.Scatter(x=tps, y=gfmi_c["q_pc"], name="GFMI_C", mode='lines', line=dict(color='red', dash='solid'), legendgroup='1'), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=gfmi_e["q_pc"], name="GFMI_E", mode='lines', line=dict(color='blue', dash='dot'), legendgroup='1'), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='q_pc', row=r, col=c) + +r, c = 3,1 +fig.add_trace(go.Scatter(x=tps, y=gfmi_c["gamma"], name="GFMI_C", mode='lines', line=dict(color='red', dash='solid'), legendgroup='1'), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=gfmi_e["gamma"], name="GFMI_E", mode='lines', line=dict(color='blue', dash='dot'), legendgroup='1'), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='gamma', row=r, col=c) + +r, c = 4,1 +fig.add_trace(go.Scatter(x=tps, y=i_vsc_dc, name="GFMI_C", mode='lines', line=dict(color='red', dash='solid'), legendgroup='1'), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=i_vsc_de, name="GFMI_E", mode='lines', line=dict(color='blue', dash='dot'), legendgroup='1'), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='i_vsc_d', row=r, col=c) + +r, c = 4,2 +fig.add_trace(go.Scatter(x=tps, y=i_vsc_qc, name="GFMI_C", mode='lines', line=dict(color='red', dash='solid'), legendgroup='1'), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=i_vsc_qe, name="GFMI_E", mode='lines', line=dict(color='blue', dash='dot'), legendgroup='1'), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='i_vsc_q', row=r, col=c) + +r, c = 5,1 +fig.add_trace(go.Scatter(x=tps, y=v_sh_dc, name="GFMI_C", mode='lines', line=dict(color='red', dash='solid'), legendgroup='1'), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=v_sh_de, name="GFMI_E", mode='lines', line=dict(color='blue', dash='dot'), legendgroup='1'), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='v_sh_d', row=r, col=c) + +r, c = 5,2 +fig.add_trace(go.Scatter(x=tps, y=v_sh_qc, name="GFMI_C", mode='lines', line=dict(color='red', dash='solid'), legendgroup='1'), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=v_sh_qe, name="GFMI_E", mode='lines', line=dict(color='blue', dash='dot'), legendgroup='1'), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='v_sh_q', row=r, col=c) + +r, c = 6,1 +fig.add_trace(go.Scatter(x=tps, y=i_bus_dc, name="GFMI_C", mode='lines', line=dict(color='red', dash='solid'), legendgroup='1'), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=i_bus_de, name="GFMI_E", mode='lines', line=dict(color='blue', dash='dot'), legendgroup='1'), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='i_bus_d', row=r, col=c) + +r, c = 6,2 +fig.add_trace(go.Scatter(x=tps, y=i_bus_qc, name="GFMI_C", mode='lines', line=dict(color='red', dash='solid'), legendgroup='1'), row=r, col=c) +fig.add_trace(go.Scatter(x=tps, y=i_bus_qe, name="GFMI_E", mode='lines', line=dict(color='blue', dash='dot'), legendgroup='1'), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='i_bus_q', row=r, col=c) + +r, c = 7,1 +fig.add_trace(go.Scatter(x=tps, y=gfmi_e["i_L"], name="GFMI_E", mode='lines', line=dict(color='blue', dash='dot'), legendgroup='1'), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='i_L', row=r, col=c) + +r, c = 7,2 +fig.add_trace(go.Scatter(x=tps, y=gfmi_e["v_dc"], name="GFMI_E", mode='lines', line=dict(color='blue', dash='dot'), legendgroup='1'), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='v_dc', row=r, col=c) + +r, c = 8,1 +fig.add_trace(go.Scatter(x=tps, y=gfmi_e["i_load"], name="GFMI_E", mode='lines', line=dict(color='blue', dash='dot'), legendgroup='1'), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='i_load', row=r, col=c) + +r, c = 8,2 +fig.add_trace(go.Scatter(x=tps, y=gfmi_e["soc"], name="GFMI_E", mode='lines', line=dict(color='blue', dash='dot'), legendgroup='1'), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='soc', row=r, col=c) + +r, c = 9,1 +p_load = np.multiply(gfmi_e["i_load"],gfmi_e["v_dc"]) +fig.add_trace(go.Scatter(x=tps, y=p_load, name="GFMI_E", mode='lines', line=dict(color='blue', dash='dot'), legendgroup='1'), row=r, col=c) +fig.update_xaxes(title_text='Time [s]', row=r, col=c) +fig.update_yaxes(title_text='p_load', row=r, col=c) + + + +# r, c = 9, 1 +# duty_cycle = self.kp_i_L*(self.kp_v_dc*(v_dc_ref - v_dcf) + x1 - i_Lf + self.Kff_idc*i_dcf + self.Kff_iload*i_loadf) + x2 +# duty_cycle = np.clip(duty_cycle, 0.0, 1.0) +# fig.add_trace(go.Scatter(x=tps, y=duty_cycle, name="duty cycle", mode='lines', line=dict(color='blue', dash='dot')), +# row=r, col=c) +# fig.update_xaxes(title_text='Time [s]', row=r, col=c) +# fig.update_yaxes(title_text='duty cycle [p.u.]', row=r, col=c) + + + +fig.update_layout(height=1200*2, + width=800*2, + legend_tracegroupgap=400, + showlegend=False, + margin={'t': 0, 'l': 0, 'b': 0, 'r': 0}) + + + +fig.show() +fig.write_html("examples/small_signal_and_emt/gfmi_e_vs_gfmi_c_emt_traces.html") + + +## Print nadir/rocof + +# Measure some performance metrics - frequency ROCOF and nadir and steady state error ? +gfm = emt_sc_c.system.gfmi_c[0].variables_emt.x.value +w_pc = gfm[1,:] +# nadir +nadir_c = np.min(w_pc) +tps = np.linspace(0, t_max, 500) +dt = tps[1] - tps[0] + +# rocof - calculate as a moving average of duration 100ms (~25 timesteps for us) +df_dt = np.abs(np.diff(w_pc)/dt) # calculate raw rocof +df_dt_ma = np.convolve(df_dt,np.ones(25)/25) # get moving averages over 25 time steps (~100ms) +rocof_c = np.max(df_dt_ma) + +gfm = emt_sc_e.system.gfmi_e[0].variables_emt.x.value +w_pc = gfm[1,:] +# nadir +nadir_e = np.min(w_pc) +tps = np.linspace(0, t_max, 500) +dt = tps[1] - tps[0] + +# rocof - calculate as a moving average of duration 100ms (~25 timesteps for us) +df_dt = np.abs(np.diff(w_pc)/dt) # calculate raw rocof +df_dt_ma = np.convolve(df_dt,np.ones(25)/25) # get moving averages over 25 time steps (~100ms) +rocof_e = np.max(df_dt_ma) + + + +# participation factor analysis - can turn this into a function / method for SSM class + +# def participation_factor_plot(ssm): +# w,vr = eig(ssm.model.A) +# vl = inv(vr) # ensures normalization + +# p = np.zeros_like(vl) +# for i in range(len(w)): +# for k in range(len(w)): +# # use correct formula for complex eigenvalues +# p[k, i] = (vl[i,k].real)**2/(np.dot(vl[i,:].real,vl[i,:].real)) # participation of k-th state (row) in i-th mode (column) + +# pf_df = pd.DataFrame(p.real, index=ssm.model.x.name) +# ax = sns.heatmap(pf_df, yticklabels=pf_df.index, xticklabels=w.real>0, linewidths=1, linecolor='white') +# ax.set_yticklabels(ax.get_yticklabels(), fontsize=8) +# ax.set_xticklabels(ax.get_xticklabels(), fontsize=8) +# plt.show() +# plt.savefig("ssm.png") + + +# participation_factor_plot(ssm_c) +# participation_factor_plot(ssm_e) + + + +print('ok') diff --git a/sting/generator/gfli_e.py b/sting/generator/gfli_e.py new file mode 100644 index 0000000..d297fa6 --- /dev/null +++ b/sting/generator/gfli_e.py @@ -0,0 +1,740 @@ +""" +This module implements a GFLI that incorporates: +- LCL filter: Two Series RL branches (one branch is the transformer) and one Parallel RC shunt. +- Outer Vdc controller +- Current controller: A dq-based frame PI controller +- PLL: A basic implementation + +in progress - Ruth (April 16) +""" +# ---------------------- +# Import python packages +# ---------------------- +import numpy as np +from dataclasses import dataclass, field +from typing import NamedTuple, Optional, ClassVar +import scipy.linalg + +# ------------------ +# Import sting code +# ------------------ +from sting.utils.dynamical_systems import StateSpaceModel, DynamicalVariables +from sting.utils.transformations import dq02abc, abc2dq0 +from sting.generator.core import Generator + +# ----------- +# Sub-classes +# ----------- +class PowerFlowVariables(NamedTuple): + p_bus: float + q_bus: float + vmag_bus: float + vphase_bus: float + + +class InitialConditionsEMT(NamedTuple): + vmag_bus: float + vphase_bus: float + p_bus: float + q_bus: float + angle_ref: float + pi_cc_d: float + pi_cc_q: float + i_vsc_d: float + i_vsc_q: float + i_bus_d: float + i_bus_q: float + v_lcl_sh_d: float + v_lcl_sh_q: float + i_bus_D: float + i_bus_Q: float + v_bus_D: float + v_bus_Q: float + v_vsc_mag: float + v_vsc_DQ_phase: float + v_vsc_d: float + v_vsc_q: float + p_vsc: float + v_dc: float + int_vdc: float + int_q: float + i_dc: float + i_load: float + + +class VariablesEMT(NamedTuple): + x: DynamicalVariables + u: DynamicalVariables + y: DynamicalVariables + +# ----------- +# Main class +# ----------- +@dataclass(slots=True, kw_only=True, eq=False) +class GFLIe(Generator): + rf1_pu: float + lf1_pu: float + rsh_pu: float + csh_pu: float + txr_power_MVA: float + txr_voltage1_kV: float + txr_voltage2_kV: float + txr_r1_pu: float + txr_l1_pu: float + txr_r2_pu: float + txr_l2_pu: float + beta: float + kp_pll: float + ki_pll: float + kp_cc: float + ki_cc: float + vdc_ref: float # added + i_load_ref: float # added + c_dc: float # added + kp_oc: float # added + ki_oc: float # added + x_pll_rescale: np.ndarray = field(default_factory=lambda: np.array([[100, 0], [0, 1]])) + name: str = field(default_factory=str) + emt_init: Optional[InitialConditionsEMT] = None + ssm: Optional[StateSpaceModel] = None + + @property + def rf2_pu(self): + return (self.txr_r1_pu + self.txr_r2_pu) * self.base_power_MVA / self.txr_power_MVA + + @property + def lf2_pu(self): + return (self.txr_l1_pu + self.txr_l2_pu) * self.base_power_MVA / self.txr_power_MVA + + @property + def wbase(self): + return 2 * np.pi * self.base_frequency_Hz + + def _build_small_signal_model(self): + + # Current PI controller + kp_cc, ki_cc = self.kp_cc, self.ki_cc + pi_cc_d, pi_cc_q = self.emt_init.pi_cc_d, self.emt_init.pi_cc_q + + pi_controller = StateSpaceModel( A = np.zeros((2,2)), + B = ki_cc*np.hstack((np.eye(2), -np.eye(2))), + C = np.eye(2), + D = kp_cc*np.hstack((np.eye(2), -np.eye(2))), + u = DynamicalVariables(name=['i_bus_d_ref', 'i_bus_q_ref', 'i_bus_d', 'i_bus_q']), + y = DynamicalVariables(name=['e_d', 'e_q']), + x = DynamicalVariables( name=['pi_cc_d', 'pi_cc_q'], + init= [pi_cc_d, pi_cc_q]) ) + + # LCL filter + rf1, lf1, rf2, lf2, rsh, csh = self.rf1_pu, self.lf1_pu, self.rf2_pu, self.lf2_pu, self.rsh_pu, self.csh_pu + wb = self.wbase + i_vsc_d, i_vsc_q = self.emt_init.i_vsc_d, self.emt_init.i_vsc_q + i_bus_d, i_bus_q = self.emt_init.i_bus_d, self.emt_init.i_bus_q + v_lcl_sh_d, v_lcl_sh_q = self.emt_init.v_lcl_sh_d, self.emt_init.v_lcl_sh_q + + lcl_filter = StateSpaceModel( + A = wb*np.array([[-rf1/lf1 , 1 , 0 , 0 , -1/lf1 , 0], + [-1 , -rf1/lf1, 0 , 0 , 0 , -1/lf1], + [0 , 0 , -rf2/lf2 , 1 , 1/lf2 , 0], + [0 , 0 , -1 , -rf2/lf2, 0 , 1/lf2], + [1/csh , 0 , -1/csh , 0 , -1/(rsh*csh), 1], + [0 , 1/csh , 0 , -1/csh , -1 , -1/(rsh*csh)]]), + B = wb*np.array([[1/lf1 , 0 , 0 , 0 , i_vsc_q], + [0 , 1/lf1 , 0 , 0 , -i_vsc_d], + [0 , 0 , -1/lf2 , 0 , i_bus_q], + [0 , 0 , 0 , -1/lf2 , -i_bus_d], + [0 , 0 , 0 , 0 , v_lcl_sh_q], + [0 , 0 , 0 , 0 , -v_lcl_sh_d]]), + C = np.eye(6), + D = np.zeros((6,5)), + x = DynamicalVariables(name=["i_vsc_d", "i_vsc_q", "i_bus_d", "i_bus_q", "v_lcl_sh_d", "v_lcl_sh_q"], + init=[i_vsc_d, i_vsc_q, i_bus_d, i_bus_q, v_lcl_sh_d, v_lcl_sh_q]), + u = DynamicalVariables(name=['v_vsc_d', 'v_vsc_q', 'v_bus_d', 'v_bus_q', 'w']), + y = DynamicalVariables(name=["i_vsc_d", "i_vsc_q", "i_bus_d", "i_bus_q", "v_lcl_sh_d", "v_lcl_sh_q"])) + + # Phase-locked loop + kp_pll, ki_pll = self.kp_pll, self.ki_pll + beta = self.beta + vmag_bus = self.emt_init.vmag_bus + sinphi = np.sin(self.emt_init.angle_ref*np.pi/180) + cosphi = np.cos(self.emt_init.angle_ref*np.pi/180) + int_pll = 0 + phase_pll = self.emt_init.angle_ref*np.pi/180 + + pll = StateSpaceModel( A = np.array([ [ 0 , -vmag_bus*ki_pll], + [wb , -wb*vmag_bus*kp_pll]]), + B = np.array([ [-sinphi*ki_pll , +cosphi*ki_pll], + [-wb*kp_pll*sinphi, wb*kp_pll*cosphi]]), + C = np.array([ [0 , 1], + [1 , -1*vmag_bus*kp_pll]]), + D = np.array([ [0 , 0], + [-1*kp_pll*sinphi , 1*kp_pll*cosphi]]), + u = DynamicalVariables(name=['v_bus_D', 'v_bus_Q']), + y = DynamicalVariables(name=['phase', 'w']), + x = DynamicalVariables(name=["int_pll", "phase_pll"], + init=[int_pll, phase_pll] ) ) + + # Re-scale the states so that they are not very small numbers compared to + # other states. It was tested in EMT simulation. + pll.A = self.x_pll_rescale @ pll.A @ scipy.linalg.inv(self.x_pll_rescale) + pll.B = self.x_pll_rescale @ pll.B + pll.C = pll.C @ scipy.linalg.inv(self.x_pll_rescale) + + # Outer control + DC capacitor dynamics + Kp, Ki, Cdc = self.kp_oc, self.ki_oc, self.c_dc + r_dc = 100 + outer_control = StateSpaceModel(A = np.array([[0, 0, Ki], + [0, 0, 0], + [0, 0, -1/r_dc]]), + B = np.array([[-Ki, 0, 0, 0, 0], + [0, 0, -Ki, Ki, 0], + [0, wb/Cdc, 0, 0, -wb/Cdc]]), + C = np.array([[1, 0, Kp], + [0, 1, 0], + [0, 0, 1]]), + D = np.array([[-Kp, 0, 0, 0, 0], + [0, 0, -Kp, Kp, 0], + [0, 0, 0, 0, 0]]), + u = DynamicalVariables(name=["vdc_ref", "i_load_ref", "q_ref", "q", "idc"]), + y = DynamicalVariables(name=["i_bus_d_ref", "i_bus_q_ref", "v_dc"]), + x = DynamicalVariables(name=["int_vdc", "int_q", "v_dc"], + init=[self.emt_init.int_vdc, self.emt_init.int_q, self.emt_init.v_dc])) + + # Construction of CCM matrices + # ustack = F*ystack + G*u + + # ustack = i2cdq, v1cdq, v2cdq, w, v2cdq, vdcref, iload, qref, q, idc (14) + # y_stack = vmd, vmq, i2d, i2q, i1d, i1q, v3d, v3q, theta, w, idref, iqref, vdc (13) - extra 4 + 3 = 7 + # u = vdcref, iload, qref, v2d, v2q + # y = i2dq + + # reactive power linearization coefficients + a1 = -self.emt_init.v_lcl_sh_d + a2 = -self.emt_init.i_bus_q + a3 = self.emt_init.v_lcl_sh_q + a4 = self.emt_init.i_bus_d + + # dc power balance linearization + b1 = self.emt_init.v_vsc_d/self.emt_init.v_dc + b2 = self.emt_init.i_vsc_d/self.emt_init.v_dc + b3 = self.emt_init.v_vsc_q/self.emt_init.v_dc # is this just 0 ? + b4 = self.emt_init.i_vsc_q/self.emt_init.v_dc + b5 = - self.emt_init.i_dc/self.emt_init.v_dc + + # Construction of CCM matrices + Fccm = np.vstack( ( np.hstack((np.zeros((10, )), 1, 0, 0)) ,# i2ref_d + np.hstack((np.zeros((10, )), 0, 1, 0)) , # i2ref_q + np.hstack((np.zeros((2,4)), np.eye(2) ,np.zeros((2,7)))), # i2c_dq + [1, 0, 0, 0, 0, -(lf1+lf2), 0, 0, 0, 0, 0, 0, 0], # v1c_d + [0, 1, 0, 0, (lf1+lf2), 0, 0, 0, -beta*vmag_bus, 0, 0, 0, 0], # v1c_q + np.zeros((13, )) , # v2c_d + np.append( np.zeros((8,)) , [-vmag_bus, 0, 0, 0, 0] ), # v2c_q + np.append( np.zeros((9,)) , [1, 0, 0, 0] ), # w + np.zeros((2, 13)), # v2c_dq + np.zeros((3, 13)), #vdcref, iload, qref + np.hstack((np.zeros(4,), [a3, a1, a2, a4], np.zeros(5,))), # q + np.hstack(([b2, b4, b1, b3], np.zeros(8,), [b5])) #idc + ) + ) + + + Gccm = np.vstack(( np.zeros((4, 5)), # i2ref_dq, i2c_dq, + [0, 0, 0, beta*cosphi , beta*sinphi], # v1c_d + [0, 0, 0, -beta*sinphi, beta*cosphi], # v1c_q + [0, 0, 0, cosphi ,sinphi], # v2c_d + [0, 0, 0, -sinphi ,cosphi], # v2c_q + np.zeros((5, )), # w + np.hstack((np.zeros((2,3)), np.eye(2) ) ), # v2dq + np.hstack((np.eye(3), np.zeros((3,2)))), # vdc_ref, iload, q_ref + np.zeros((2,5)) # q, idc + ) + ) + + Hccm = np.vstack(( [ 0, 0 , 0, 0, cosphi , -sinphi, 0, 0, -sinphi*i_bus_d-cosphi*i_bus_q, 0, 0, 0, 0], + [0, 0, 0, 0, sinphi , cosphi , 0, 0, cosphi*i_bus_d-sinphi*i_bus_q, 0, 0, 0, 0] )) + + Lccm = np.zeros((2, 5)) + + components = [pi_controller, lcl_filter, pll, outer_control] + connections = [Fccm, Gccm, Hccm, Lccm] + + # Inputs and outputs + v_bus_D, v_bus_Q= self.emt_init.v_bus_D, self.emt_init.v_bus_Q + u = DynamicalVariables( + name=["vdc_ref", "i_load_ref", "q_ref", "v_bus_D", "v_bus_Q"], + type=["device", "device", "device", "grid", "grid"], + init=[self.vdc_ref, self.emt_init.i_dc, self.emt_init.q_bus, v_bus_D, v_bus_Q]) + + i_bus_D, i_bus_Q= self.emt_init.i_bus_D, self.emt_init.i_bus_Q + y = DynamicalVariables( + name=['i_bus_D', 'i_bus_Q'], + init=[i_bus_D, i_bus_Q]) + + # Generate small-signal model + ssm = StateSpaceModel.from_interconnected(components, connections, u, y, component_label=f"{self.type_}_{self.id}") + + self.ssm = ssm + + def _calculate_emt_initial_conditions(self): + + + # Extract power flow solution + vmag_bus = self.power_flow_variables.vmag_bus + vphase_bus = self.power_flow_variables.vphase_bus + p_bus = self.power_flow_variables.p_bus + q_bus = self.power_flow_variables.q_bus + + # Voltage in the end of the LCL filter + v_bus_DQ = vmag_bus * np.exp(vphase_bus * np.pi / 180 * 1j) + angle_ref = np.angle(v_bus_DQ, deg=True) + + # Current sent from the end of the LCL filter + i_bus_DQ = (p_bus - q_bus * 1j) / np.conjugate(v_bus_DQ) + + # Voltage across the shunt element in the LCL filter + v_lcl_sh_DQ = v_bus_DQ + (self.rf2_pu + self.lf2_pu * 1j) * i_bus_DQ + + # Current flowing through shunt element of LCL filter + i_lcl_sh_DQ = v_lcl_sh_DQ * (self.csh_pu * 1j) + v_lcl_sh_DQ / self.rsh_pu + + # Current sent from the beginning of the LCL filter + i_vsc_DQ = i_bus_DQ + i_lcl_sh_DQ + v_vsc_DQ = v_lcl_sh_DQ + (self.rf1_pu + self.lf1_pu * 1j) * i_vsc_DQ + + # We refer the voltage and currents to the synchronous frames of the + # inverter + v_vsc_dq = v_vsc_DQ * np.exp(-angle_ref * np.pi / 180 * 1j) + i_vsc_dq = i_vsc_DQ * np.exp(-angle_ref * np.pi / 180 * 1j) + + v_bus_dq = v_bus_DQ * np.exp(-angle_ref * np.pi / 180 * 1j) + i_bus_dq = i_bus_DQ * np.exp(-angle_ref * np.pi / 180 * 1j) + + v_lcl_sh_dq = v_lcl_sh_DQ * np.exp(-angle_ref * np.pi / 180 * 1j) + + # Initial conditions for the integral controller + pi_cc_dq = ( + v_vsc_dq - self.beta * v_bus_dq - 1j * (self.lf1_pu + self.lf2_pu) * i_bus_dq + ) + + + # Initial conditions for outer control / dc + + # DC-side initial conditions + v_dc = self.vdc_ref + p_vsc = (v_vsc_dq*np.conjugate(i_vsc_dq)).real # power at converter terminals + i_dc = p_vsc/v_dc + + self.emt_init = InitialConditionsEMT( + vmag_bus=vmag_bus, + vphase_bus=vphase_bus, + p_bus=p_bus, + q_bus=q_bus, + angle_ref=angle_ref, + pi_cc_d=pi_cc_dq.real, + pi_cc_q=pi_cc_dq.imag, + i_vsc_d=i_vsc_dq.real, + i_vsc_q=i_vsc_dq.imag, + i_bus_d=i_bus_dq.real, + i_bus_q=i_bus_dq.imag, + v_lcl_sh_d=v_lcl_sh_dq.real, + v_lcl_sh_q=v_lcl_sh_dq.imag, + i_bus_D=i_bus_DQ.real, + i_bus_Q=i_bus_DQ.imag, + v_bus_D=v_bus_DQ.real, + v_bus_Q=v_bus_DQ.imag, + v_vsc_mag = abs(v_vsc_DQ), + v_vsc_DQ_phase = np.angle(v_vsc_DQ, deg=True), + v_dc=v_dc, + p_vsc=p_vsc, + i_dc=i_dc, + int_vdc=i_bus_dq.real, + int_q=i_bus_dq.imag, + i_load=i_dc, + v_vsc_d=v_vsc_dq.real, + v_vsc_q=v_vsc_dq.imag + + ) + + def define_variables_emt(self): + # States + # ------ + + + + x = DynamicalVariables( + name = [], + component = f"{self.type_}_{self.id}", + init=[] + ) + + # Inputs + # ------ + + # Initial conditions + + u = DynamicalVariables( + name=["vdc_ref", "iload", "q_ref", "v_bus_a", "v_bus_b", "v_bus_c"], + component=f"{self.type_}_{self.id}", + type=["device", "device", "device", "grid", "grid"], + init=[] + ) + + # Outputs + # ------- + + y = DynamicalVariables( + name=["i_bus_a", "i_bus_b", "i_bus_c"], + component=f"{self.type_}_{self.id}", + init=[i_bus_a, i_bus_b, i_bus_c] + ) + + self.variables_emt = VariablesEMT(x=x,u=u,y=y) + + + def get_derivative_state_emt(self): + + # Get state values + # outer control / current control / lcl / pll + angle_pc, w_pc, p_pc, q_pc, gamma, i_vsc_a, i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c, i_Lf, v_dcf, i_dcf, i_loadf, x1, x2, i_L, v_dc, i_load, soc, x3 = self.variables_emt.x.value + + # Get input values (external inputs) + vdc_ref, iload, qref, v_bus_a, v_bus_b, v_bus_c = self.variables_emt.u.value + + # convert relevant quantities to dq (ibr frame) + v_sh_d, v_sh_q, _ = abc2dq0(v_sh_a, v_sh_b, v_sh_c, angle_pc) # for power controller + i_bus_d, i_bus_q, _ = abc2dq0(i_bus_a, i_bus_b, i_bus_c, angle_pc) # for power controller + i_vsc_d, i_vsc_q, _ = abc2dq0(i_vsc_a, i_vsc_b, i_vsc_c, angle_pc) + + # outer control + id_ref = int_vdc + self.kp_oc*(vdc_ref - v_dc) + iq_ref = int_q + self.kp_oc*(qref - q) + + # current controller + vmd = self.ki_cc*gamma_d + self.kp_cc*(id_ref - i_d) + vmq = self.ki_cc*gamma_q + self.kp_cc*(id_ref - i_d) + + # PLL + + + # Do Q-V droop + v_sh_mag_ref = v_ref - self.droop_q_pu*(q_pc - q_ref) # adjusting voltage reference based on reactive power error (measured at capacitor) + + # NB updating algebraic states! + # Updating converter terminal voltages + v_vsc_d = gamma + self.kp_vc_pu*(v_sh_mag_ref - (v_sh_d**2 + v_sh_q**2)**0.5) # update + v_vsc_q = 0.0 # update + + # # check magnitude wrt v_dc and limit if necessary + # if v_vsc_d > v_dc: # can check only d component because v_vsc_q= 0 + # v_vsc_d = v_dc + + # convert to abc to feed into filter dynamics + v_vsc_a, v_vsc_b, v_vsc_c = dq02abc(v_vsc_d, v_vsc_q, 0, angle_pc) # correct to use this angle? + + # DC/AC power balance + i_dc = (v_vsc_d*i_vsc_d + v_vsc_q*i_vsc_q)/v_dc + + + + # Differential equations + # ---------------------- + + # Power controller: + def outer_loop_dynamics(y, internal_inputs): + """ + PI control of Vdc error to generate id_ref + PI control of Q error to generate iq_ref + """ + int_vdc, int_q, v_dc = y[0], y[1], y[2] + + vdc_ref, iload, qref, idc, q = internal_inputs + + d_int_vdc = self.Ki_oc*(v_dc_ref - v_dc) + d_int_q = self.Ki_oc*(qref - q) + d_v_dc = (-self.wbase/self.cdc)*(idc - iload) + + return [d_int_vdc, d_int_q, d_v_dc] + + + def current_controller_dynamics(y, internal_inputs): + """ + decoupled PI controllers + """ + gamma = y[0] + + id_ref, iq_ref, id, iq = internal_inputs + + d_gamma_d = id_ref - id + d_gamma_q = iq_ref - iq + + return [d_gamma_d, d_gamma_q] + + + def lcl_filter_dynamics(y, internal_inputs): + """ + The LCL filter connects the VSC to the grid. It has three branches: the first branch (RL) connects + the VSC to the shunt element, the second branch is the shunt element (RC), and the third branch (RL) + connects the shunt element to the grid. + """ + + # Definition of states for the ODEs of the LCL filter + i_vsc_a , i_vsc_b, i_vsc_c = y[0], y[1], y[2] # currents flowing out of VSC + v_sh_a, v_sh_b, v_sh_c = y[3], y[4], y[5] # currents flowing through paralell RC shunt + i_bus_a, i_bus_b, i_bus_c = y[6], y[7], y[8] # currents flowing to bus + + # Extract the list of parameters + rf1, xf1, rf2, xf2, rsh, csh = self.rf1_pu, self.xf1_pu, self.rf2_pu, self.xf2_pu, self.rsh_pu, self.csh_pu + wb = self.wbase + r1 = rf1 + r2 = rf2 + x1 = xf1 + x2 = xf2 + + # Inputs + v_vsc_a, v_vsc_b, v_vsc_c, v_bus_a, v_bus_b, v_bus_c = internal_inputs + + # Define ODEs that describe the dynamics of the LCL filter + di_vsc_a = wb/x1 *(v_vsc_a - v_sh_a - r1 * i_vsc_a) + di_vsc_b = wb/x1 *(v_vsc_b - v_sh_b - r1 * i_vsc_b) + di_vsc_c = wb/x1 *(v_vsc_c - v_sh_c - r1 * i_vsc_c) + + dv_sh_a = wb/csh * (-v_sh_a/rsh + i_vsc_a - i_bus_a) + dv_sh_b = wb/csh * (-v_sh_b/rsh + i_vsc_b - i_bus_b) + dv_sh_c = wb/csh * (-v_sh_c/rsh + i_vsc_c - i_bus_c) + + di_bus_a = wb/x2 *(v_sh_a - v_bus_a - r2 * i_bus_a) + di_bus_b = wb/x2 *(v_sh_b - v_bus_b - r2 * i_bus_b) + di_bus_c = wb/x2 *(v_sh_c - v_bus_c - r2 * i_bus_c) + + return [di_vsc_a, di_vsc_b, di_vsc_c, dv_sh_a, dv_sh_b, dv_sh_c, di_bus_a, di_bus_b, di_bus_c] + + + def pll_dynamics(y, internal_inputs): + """ + """ + + int_pll, theta = y[0], y[1] + + v_bus_q = internal_inputs + + d_int_pll = self.ki_pll*(v_bus_q) + d_theta = self.wbase*self.ki_pll*int_pll - self.wbase*vm*self.kp_pll*theta + + return [d_int_pll, d_theta] + + + dy_pc = outer_loop_dynamics([angle_pc, w_pc, p_pc, q_pc], [v_sh_d, v_sh_q, i_bus_d, i_bus_q, p_ref]) + dy_vc = current_controller_dynamics([gamma], [v_sh_mag_ref, v_sh_d, v_sh_q]) + dy_lcl = lcl_filter_dynamics([i_vsc_a , i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c], [v_vsc_a, v_vsc_b, v_vsc_c, v_bus_a, v_bus_b, v_bus_c]) + dy_pll = pll_dynamics([int_pll, theta], [v_sh_a, v_sh_b, v_sh_c]) + + return np.hstack([dy_pc, dy_vc, dy_lcl]) + + + def get_output_emt(self): + + # Output is i_bus_abc + angle_pc, w_pc, p_pc, q_pc, gamma, i_vsc_a, i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c, i_Lf, v_dcf, i_dcf, i_loadf, x1, x2, i_L, v_dc, i_load, soc, x3 = self.variables_emt.x.value + + return [i_bus_a, i_bus_b, i_bus_c] + + def plot_results_emt(self, output_dir): + + angle_pc, w_pc, p_pc, q_pc, gamma, i_vsc_a, i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c, i_Lf, v_dcf, i_dcf, i_loadf, x1, x2, i_L, v_dc, i_load, soc, x3 = self.variables_emt.x.value + + #i_L = np.clip(i_L, -1000.0, 1.0) + + tps = self.variables_emt.x.time + + # Transform abc to dq0 + i_vsc_d, i_vsc_q, _ = zip(*[abc2dq0(a, b, c, ang) for a, b, c, ang in zip(i_vsc_a, i_vsc_b, i_vsc_c, angle_pc)]) + v_sh_d, v_sh_q, _ = zip(*[abc2dq0(a, b, c, ang) for a, b, c, ang in zip(v_sh_a, v_sh_b, v_sh_c, angle_pc)]) + i_bus_d, i_bus_q, _ = zip(*[abc2dq0(a, b, c, ang) for a, b, c, ang in zip(i_bus_a, i_bus_b, i_bus_c, angle_pc)]) + + # calculate v_vsc + v_sh_dq = v_sh_d + np.multiply(v_sh_q, 1j) + i_vsc_dq = i_vsc_d + np.multiply(i_vsc_q, 1j) + v_vsc_dq = v_sh_dq + np.multiply((self.rf1_pu + self.xf1_pu * 1j), i_vsc_dq) + + fig = make_subplots( + rows=14, cols=2, + horizontal_spacing=0.15, + vertical_spacing=0.05, + ) + + fig.add_trace(go.Scatter(x=tps, y=w_pc, mode='lines', line=dict(color='red', dash='solid')), + row=1, col=1) + fig.update_xaxes(title_text='Time [s]', row=1, col=1) + fig.update_yaxes(title_text='Frequency pc [p.u.]', row=1, col=1) + + fig.add_trace(go.Scatter(x=tps, y=angle_pc * 180 / np.pi, mode='lines', line=dict(color='red', dash='solid')), + row=1, col=2) + fig.update_xaxes(title_text='Time [s]', row=1, col=2) + fig.update_yaxes(title_text='Angle pc [deg]', row=1, col=2) + + fig.add_trace(go.Scatter(x=tps, y=p_pc, name="p_pc", mode='lines', line=dict(color='red', dash='solid')), + row=2, col=1) + fig.update_xaxes(title_text='Time [s]', row=2, col=1) + fig.update_yaxes(title_text='Active Power pc [p.u.]', row=2, col=1) + + fig.add_trace(go.Scatter(x=tps, y=q_pc, mode='lines', line=dict(color='red', dash='solid')), + row=2, col=2) + fig.update_xaxes(title_text='Time [s]', row=2, col=2) + fig.update_yaxes(title_text='Reactive Power pc [p.u.]', row=2, col=2) + + fig.add_trace(go.Scatter(x=tps, y=gamma, mode='lines', line=dict(color='red', dash='solid')), + row=3, col=1) + fig.update_xaxes(title_text='Time [s]', row=3, col=1) + fig.update_yaxes(title_text='Gamma [p.u.]', row=3, col=1) + + fig.add_trace(go.Scatter(x=tps, y=i_loadf, mode='lines', line=dict(color='red', dash='solid')), + row=3, col=2) + fig.update_xaxes(title_text='Time [s]', row=3, col=2) + fig.update_yaxes(title_text='iload_f [p.u.]', row=3, col=2) + + fig.add_trace(go.Scatter(x=tps, y=i_vsc_d, mode='lines', line=dict(color='red', dash='solid')), + row=4, col=1) + fig.update_xaxes(title_text='Time [s]', row=4, col=1) + fig.update_yaxes(title_text='i_vsc_d [p.u.]', row=4, col=1) + + fig.add_trace(go.Scatter(x=tps, y=i_vsc_q, mode='lines', line=dict(color='red', dash='solid')), + row=4, col=2) + fig.update_xaxes(title_text='Time [s]', row=4, col=2) + fig.update_yaxes(title_text='i_vsc_q [p.u.]', row=4, col=2) + + fig.add_trace(go.Scatter(x=tps, y=v_sh_d, mode='lines', line=dict(color='red', dash='solid')), + row=5, col=1) + fig.update_xaxes(title_text='Time [s]', row=5, col=1) + fig.update_yaxes(title_text='v_sh_d [p.u.]', row=5, col=1) + + fig.add_trace(go.Scatter(x=tps, y=v_sh_q, mode='lines', line=dict(color='red', dash='solid')), + row=5, col=2) + fig.update_xaxes(title_text='Time [s]', row=5, col=2) + fig.update_yaxes(title_text='v_sh_q [p.u.]', row=5, col=2) + + fig.add_trace(go.Scatter(x=tps, y=i_bus_d, mode='lines', line=dict(color='red', dash='solid')), + row=6, col=1) + fig.update_xaxes(title_text='Time [s]', row=6, col=1) + fig.update_yaxes(title_text='i_bus_d [p.u.]', row=6, col=1) + + fig.add_trace(go.Scatter(x=tps, y=i_bus_q, mode='lines', line=dict(color='red', dash='solid')), + row=6, col=2) + fig.update_xaxes(title_text='Time [s]', row=6, col=2) + fig.update_yaxes(title_text='i_bus_q [p.u.]', row=6, col=2) + + fig.add_trace(go.Scatter(x=tps, y=v_dc, mode='lines', line=dict(color='red', dash='solid')), + row=7, col=1) + fig.update_xaxes(title_text='Time [s]', row=7, col=1) + fig.update_yaxes(title_text='v_dc [p.u.]', row=7, col=1) + + fig.add_trace(go.Scatter(x=tps, y=i_L, mode='lines', line=dict(color='red', dash='solid')), + row=7, col=2) + fig.update_xaxes(title_text='Time [s]', row=7, col=2) + fig.update_yaxes(title_text='i_L [p.u.]', row=7, col=2) + + + fig.add_trace(go.Scatter(x=tps, y=v_dcf, mode='lines', line=dict(color='red', dash='solid')), + row=8, col=1) + fig.update_xaxes(title_text='Time [s]', row=8, col=1) + fig.update_yaxes(title_text='v_dcf [p.u.]', row=8, col=1) + + fig.add_trace(go.Scatter(x=tps, y=i_Lf, mode='lines', line=dict(color='red', dash='solid')), + row=8, col=2) + fig.update_xaxes(title_text='Time [s]', row=8, col=2) + fig.update_yaxes(title_text='i_Lf [p.u.]', row=8, col=2) + + + fig.add_trace(go.Scatter(x=tps, y=i_dcf, mode='lines', line=dict(color='red', dash='solid')), + row=9, col=1) + fig.update_xaxes(title_text='Time [s]', row=9, col=1) + fig.update_yaxes(title_text='i_dcf [p.u.]', row=9, col=1) + + fig.add_trace(go.Scatter(x=tps, y=x1, mode='lines', line=dict(color='red', dash='solid')), + row=9, col=2) + fig.update_xaxes(title_text='Time [s]', row=9, col=2) + fig.update_yaxes(title_text='x1 [p.u.]', row=9, col=2) + + fig.add_trace(go.Scatter(x=tps, y=x2, mode='lines', line=dict(color='red', dash='solid')), + row=10, col=1) + fig.update_xaxes(title_text='Time [s]', row=10, col=1) + fig.update_yaxes(title_text='x2 [p.u.]', row=10, col=1) + + fig.add_trace(go.Scatter(x=tps, y=i_load, mode='lines', line=dict(color='red', dash='solid')), + row=10, col=2) + fig.update_xaxes(title_text='Time [s]', row=10, col=2) + fig.update_yaxes(title_text='i_load [p.u.]', row=10, col=2) + + # power comparisons (calculated) + p_vsc = (v_vsc_dq*np.conjugate(i_vsc_dq)).real + p_load = i_load*v_dc + p_ref, q_ref, v_ref, v_dc_ref, v_s, i_load_ref, v_bus_a, v_bus_b, v_bus_c = self.variables_emt.u.value + p_bat = i_L*v_s + p_capacitor = p_vsc + p_load - p_bat + fig.add_trace(go.Scatter(x=tps, y=p_vsc, name="p_vsc", mode='lines', line=dict(color='red', dash='solid')), + row=11, col=1) + fig.add_trace(go.Scatter(x=tps, y=p_load, name="p_load", mode='lines', line=dict(color='blue', dash='solid')), + row=11, col=1) + fig.add_trace(go.Scatter(x=tps, y=p_bat, name="p_bat", mode='lines', line=dict(color='green', dash='solid')), + row=11, col=1) + fig.add_trace(go.Scatter(x=tps, y=p_capacitor, name="p_cap", mode='lines', line=dict(color='pink', dash='solid')), + row=11, col=1) + + fig.add_trace(go.Scatter(x=tps, y=np.ones_like(p_bat)*self.Pbat_max_pu, name="p_bat_lim", mode='lines', line=dict(color='green', dash='dot')), + row=11, col=1) + + fig.update_xaxes(title_text='Time [s]', row=11, col=1) + fig.update_yaxes(title_text='p [p.u.]', row=11, col=1) + + # v_vsc (calculated) + fig.add_trace(go.Scatter(x=tps, y=v_vsc_dq.real, mode='lines', line=dict(color='red', dash='solid')), + row=12, col=1) + fig.update_xaxes(title_text='Time [s]', row=12, col=1) + fig.update_yaxes(title_text='v_vsc_d [p.u.]', row=12, col=1) + + fig.add_trace(go.Scatter(x=tps, y=v_vsc_dq.imag, mode='lines', line=dict(color='red', dash='solid')), + row=12, col=2) + fig.update_xaxes(title_text='Time [s]', row=12, col=2) + fig.update_yaxes(title_text='v_vsc_q [p.u.]', row=12, col=2) + + e_cap = 0.5*self.c_dc*(v_dc**2) + e_ind = 0.5*self.l_dc*(i_L**2) + fig.add_trace(go.Scatter(x=tps, y=soc, name='battery soc', mode='lines', line=dict(color='red', dash='solid')), + row=13, col=1) + fig.add_trace(go.Scatter(x=tps, y=e_cap, name='cap energy', mode='lines', line=dict(color='blue', dash='dot')), + row=13, col=1) + fig.add_trace(go.Scatter(x=tps, y=e_ind, name='ind energy', mode='lines', line=dict(color='pink', dash='dot')), + row=13, col=1) + + fig.add_trace(go.Scatter(x=tps, y=np.ones_like(soc)*self.SOC_max_pu, name="soc lim", mode='lines', line=dict(color='green', dash='dot')), + row=13, col=1) + fig.update_xaxes(title_text='Time [s]', row=13, col=1) + fig.update_yaxes(title_text='energy [p.u.]', row=13, col=1) + + duty_cycle = self.kp_i_L*(self.kp_v_dc*(v_dc_ref - v_dcf) + x1 - i_Lf + self.Kff_idc*i_dcf + self.Kff_iload*i_loadf) + x2 + duty_cycle = np.clip(duty_cycle, 0.0, 1.0) + fig.add_trace(go.Scatter(x=tps, y=duty_cycle, name="duty cycle", mode='lines', line=dict(color='red', dash='solid')), + row=13, col=2) + fig.update_xaxes(title_text='Time [s]', row=13, col=2) + fig.update_yaxes(title_text='duty cycle [p.u.]', row=13, col=2) + + fig.add_trace(go.Scatter(x=tps, y=x3, mode='lines', line=dict(color='red', dash='solid')), + row=14, col=1) + fig.update_xaxes(title_text='Time [s]', row=14, col=1) + fig.update_yaxes(title_text='x3 [p.u.]', row=14, col=1) + + + name = f"{self.type_}_{self.id}" + fig.update_layout( title_text = name, + title_x=0.5, + showlegend = False, + ) + + fig.update_layout(height=1200*2, + width=800*2, + showlegend=False, + margin={'t': 0, 'l': 0, 'b': 0, 'r': 0}) + + fig.write_html(os.path.join(output_dir, name + ".html")) + + + \ No newline at end of file diff --git a/sting/generator/gfmi_e.py b/sting/generator/gfmi_e.py index 99cb9db..7a06f9f 100644 --- a/sting/generator/gfmi_e.py +++ b/sting/generator/gfmi_e.py @@ -113,12 +113,12 @@ class GFMIe(Generator): Ti_load: float # for DC/DC controller - measurement filter Tload: float # time constant for actuation of load current change i_load_ref: float - #bus_id: int = None + Pbat_max_pu: float # maximum power capacity of battery (pu by S) + SOC_max_pu: float # maximum energy capacity of battery (pu by S) + SOC_init_pu: float # initial battery state of charge (pu) name: str = field(default_factory=str) - #pf: Optional[Power_flow_variables] = None emt_init: Optional[InitialConditionsEMT] = None ssm: Optional[StateSpaceModel] = None - #tags: ClassVar[list[str]] = ["generator"] @property def rf2_pu(self): @@ -470,9 +470,9 @@ def define_variables_emt(self): v_dc, i_dc, i_L, x1, x2, i_load = self.emt_init.v_dc, self.emt_init.i_dc, self.emt_init.i_L, self.emt_init.x_1, self.emt_init.x_2, self.emt_init.i_load x = DynamicalVariables( - name = ['angle_pc', 'w_pc', 'p_pc', 'q_pc', 'gamma',"i_vsc_a", "i_vsc_b","i_vsc_c", "v_sh_a", "v_sh_b","v_sh_c", "i_bus_a", "i_bus_b", "i_bus_c", 'i_l_f', 'v_dc_f', 'i_dc_f', 'i_load_f','x_1', 'x_2', 'i_L', 'v_dc', 'i_load'], + name = ['angle_pc', 'w_pc', 'p_pc', 'q_pc', 'gamma',"i_vsc_a", "i_vsc_b","i_vsc_c", "v_sh_a", "v_sh_b","v_sh_c", "i_bus_a", "i_bus_b", "i_bus_c", 'i_l_f', 'v_dc_f', 'i_dc_f', 'i_load_f','x_1', 'x_2', 'i_L', 'v_dc', 'i_load', 'soc', 'x3'], component = f"{self.type_}_{self.id}", - init=[angle_ref*np.pi/180, 1.0, p_ref, q_ref, v_vsc_d, i_vsc_a, i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c, i_L, v_dc, i_dc, i_load, x1, x2, i_L, v_dc, i_load] + init=[angle_ref*np.pi/180, 1.0, p_ref, q_ref, v_vsc_d, i_vsc_a, i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c, i_L, v_dc, i_dc, i_load, x1, x2, i_L, v_dc, i_load, self.SOC_init_pu, 0.0] ) # Inputs @@ -504,7 +504,7 @@ def define_variables_emt(self): def get_derivative_state_emt(self): # Get state values - angle_pc, w_pc, p_pc, q_pc, gamma, i_vsc_a, i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c, i_Lf, v_dcf, i_dcf, i_loadf, x1, x2, i_L, v_dc, i_load = self.variables_emt.x.value + angle_pc, w_pc, p_pc, q_pc, gamma, i_vsc_a, i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c, i_Lf, v_dcf, i_dcf, i_loadf, x1, x2, i_L, v_dc, i_load, soc, x3 = self.variables_emt.x.value # Get input values (external inputs) p_ref, q_ref, v_ref, v_dc_ref, v_s, i_load_ref, v_bus_a, v_bus_b, v_bus_c = self.variables_emt.u.value @@ -515,20 +515,24 @@ def get_derivative_state_emt(self): i_vsc_d, i_vsc_q, _ = abc2dq0(i_vsc_a, i_vsc_b, i_vsc_c, angle_pc) # Do Q-V droop - v_sh_mag_ref = v_ref - self.droop_q_pu*(q_pc - q_ref) # droop on error from ref + v_sh_mag_ref = v_ref - self.droop_q_pu*(q_pc - q_ref) # adjusting voltage reference based on reactive power error (measured at capacitor) # NB updating algebraic states! + # Updating converter terminal voltages v_vsc_d = gamma + self.kp_vc_pu*(v_sh_mag_ref - (v_sh_d**2 + v_sh_q**2)**0.5) # update v_vsc_q = 0.0 # update + # # check magnitude wrt v_dc and limit if necessary + # if v_vsc_d > v_dc: # can check only d component because v_vsc_q= 0 + # v_vsc_d = v_dc + # convert to abc to feed into filter dynamics v_vsc_a, v_vsc_b, v_vsc_c = dq02abc(v_vsc_d, v_vsc_q, 0, angle_pc) # correct to use this angle? - # power balance + # DC/AC power balance i_dc = (v_vsc_d*i_vsc_d + v_vsc_q*i_vsc_q)/v_dc - # abc->dq conversions # Differential equations # ---------------------- @@ -623,7 +627,7 @@ def dc_side(y, internal_inputs): DC-DC controller + circuit + load control """ # Define states - i_Lf, v_dcf, i_dcf, i_loadf, x_1, x_2, i_L, v_dc, i_load = y[0], y[1], y[2], y[3], y[4], y[5], y[6], y[7], y[8] + i_Lf, v_dcf, i_dcf, i_loadf, x_1, x_2, i_L, v_dc, i_load, soc = y[0], y[1], y[2], y[3], y[4], y[5], y[6], y[7], y[8], y[9] # Inputs i_dc, i_load_ref, v_dc_ref, v_s = internal_inputs @@ -632,6 +636,11 @@ def dc_side(y, internal_inputs): l_dc, c_dc, TiL, Tvdc, Tidc, Kp_vdc, Ki_vdc, Kp_iL, Ki_iL, Kff_idc, Kff_iload, Ti_load, Tload = self.l_dc, self.c_dc, self.Ti_L, self.Tv_dc, self.Ti_dc, self.kp_v_dc, self.ki_v_dc, self.kp_i_L, self.ki_i_L, self.Kff_idc, self.Kff_iload, self.Ti_load, self.Tload wb = self.wbase + # # DC side limits + # # P_battery = i_L*v_s + # if i_L > 1.0: + # i_L = 1.0 + # ODEs # DC-DC controller @@ -643,6 +652,14 @@ def dc_side(y, internal_inputs): d_x_2 = Ki_iL*(Kp_vdc*(v_dc_ref - v_dcf) + x_1 - i_Lf + Kff_idc*i_dcf + Kff_iload*i_loadf) duty_cycle = Kp_iL*(Kp_vdc*(v_dc_ref - v_dcf) + x_1 - i_Lf + Kff_idc*i_dcf + Kff_iload*i_loadf) + x_2 + # # limit duty cycle + # if duty_cycle > 0.9: + # duty_cycle = 0.9 + + d_soc = i_L*v_s + # soc controller + d_x3 = (soc - self.SOC_init_pu) + # Circuit equations d_v_dc = (wb/c_dc)*(-i_dc - i_load + (1-duty_cycle)*i_L) d_i_L = (wb/l_dc)*(v_s - (1-duty_cycle)*v_dc) @@ -650,14 +667,13 @@ def dc_side(y, internal_inputs): # Load control d_i_load = (1/Tload)*(i_load_ref - i_load) - return [d_i_Lf, d_v_dcf, d_i_dcf, d_i_load_f, d_x_1, d_x_2, d_i_L, d_v_dc, d_i_load] - #return [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] + return [d_i_Lf, d_v_dcf, d_i_dcf, d_i_load_f, d_x_1, d_x_2, d_i_L, d_v_dc, d_i_load, d_soc, d_x3] dy_pc = power_controller_dynamics([angle_pc, w_pc, p_pc, q_pc], [v_sh_d, v_sh_q, i_bus_d, i_bus_q, p_ref]) dy_vc = voltage_controller_dynamics([gamma], [v_sh_mag_ref, v_sh_d, v_sh_q]) dy_lcl = lcl_filter_dynamics([i_vsc_a , i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c], [v_vsc_a, v_vsc_b, v_vsc_c, v_bus_a, v_bus_b, v_bus_c]) - dy_dc_side = dc_side([i_Lf, v_dcf, i_dcf, i_loadf, x1, x2, i_L, v_dc, i_load], [i_dc, i_load_ref, v_dc_ref, v_s]) + dy_dc_side = dc_side([i_Lf, v_dcf, i_dcf, i_loadf, x1, x2, i_L, v_dc, i_load, soc, x3], [i_dc, i_load_ref, v_dc_ref, v_s]) return np.hstack([dy_pc, dy_vc, dy_lcl, dy_dc_side]) @@ -665,13 +681,15 @@ def dc_side(y, internal_inputs): def get_output_emt(self): # Output is i_bus_abc - angle_pc, w_pc, p_pc, q_pc, gamma, i_vsc_a, i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c, i_Lf, v_dcf, i_dcf, i_loadf, x1, x2, i_L, v_dc, i_load = self.variables_emt.x.value + angle_pc, w_pc, p_pc, q_pc, gamma, i_vsc_a, i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c, i_Lf, v_dcf, i_dcf, i_loadf, x1, x2, i_L, v_dc, i_load, soc, x3 = self.variables_emt.x.value return [i_bus_a, i_bus_b, i_bus_c] def plot_results_emt(self, output_dir): - angle_pc, w_pc, p_pc, q_pc, gamma, i_vsc_a, i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c, i_Lf, v_dcf, i_dcf, i_loadf, x1, x2, i_L, v_dc, i_load = self.variables_emt.x.value + angle_pc, w_pc, p_pc, q_pc, gamma, i_vsc_a, i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c, i_Lf, v_dcf, i_dcf, i_loadf, x1, x2, i_L, v_dc, i_load, soc, x3 = self.variables_emt.x.value + + #i_L = np.clip(i_L, -1000.0, 1.0) tps = self.variables_emt.x.time @@ -686,9 +704,7 @@ def plot_results_emt(self, output_dir): v_vsc_dq = v_sh_dq + np.multiply((self.rf1_pu + self.xf1_pu * 1j), i_vsc_dq) fig = make_subplots( - rows=12, cols=2, - horizontal_spacing=0.15, - vertical_spacing=0.05, + rows=14, cols=2 ) fig.add_trace(go.Scatter(x=tps, y=w_pc, mode='lines', line=dict(color='red', dash='solid')), @@ -721,8 +737,6 @@ def plot_results_emt(self, output_dir): fig.update_xaxes(title_text='Time [s]', row=3, col=2) fig.update_yaxes(title_text='iload_f [p.u.]', row=3, col=2) - - fig.add_trace(go.Scatter(x=tps, y=i_vsc_d, mode='lines', line=dict(color='red', dash='solid')), row=4, col=1) fig.update_xaxes(title_text='Time [s]', row=4, col=1) @@ -800,16 +814,20 @@ def plot_results_emt(self, output_dir): p_load = i_load*v_dc p_ref, q_ref, v_ref, v_dc_ref, v_s, i_load_ref, v_bus_a, v_bus_b, v_bus_c = self.variables_emt.u.value p_bat = i_L*v_s - fig.add_trace(go.Scatter(x=tps, y=p_vsc, name="p_vsc", mode='lines', line=dict(color='red', dash='solid')), + p_capacitor = p_vsc + p_load - p_bat + fig.add_trace(go.Scatter(x=tps, y=p_vsc, name="p_vsc", mode='lines', line=dict(color='red', dash='solid'), legendgroup='1'), row=11, col=1) - fig.add_trace(go.Scatter(x=tps, y=p_load, name="p_load", mode='lines', line=dict(color='blue', dash='solid')), + fig.add_trace(go.Scatter(x=tps, y=p_load, name="p_load", mode='lines', line=dict(color='blue', dash='solid'), legendgroup='1'), row=11, col=1) - fig.add_trace(go.Scatter(x=tps, y=p_bat, name="p_bat", mode='lines', line=dict(color='green', dash='solid')), + fig.add_trace(go.Scatter(x=tps, y=p_bat, name="p_bat", mode='lines', line=dict(color='green', dash='solid'), legendgroup='1'), + row=11, col=1) + fig.add_trace(go.Scatter(x=tps, y=p_capacitor, name="p_cap", mode='lines', line=dict(color='pink', dash='solid'), legendgroup='1'), + row=11, col=1) + fig.add_trace(go.Scatter(x=tps, y=np.ones_like(p_bat)*self.Pbat_max_pu, name="p_bat_lim", mode='lines', line=dict(color='green', dash='dot'), legendgroup='1'), row=11, col=1) - fig.update_xaxes(title_text='Time [s]', row=11, col=1) - fig.update_yaxes(title_text='p [p.u.]', row=11, col=1) + fig.update_yaxes(title_text='power [p.u.]', row=11, col=1) # v_vsc (calculated) fig.add_trace(go.Scatter(x=tps, y=v_vsc_dq.real, mode='lines', line=dict(color='red', dash='solid')), @@ -822,6 +840,32 @@ def plot_results_emt(self, output_dir): fig.update_xaxes(title_text='Time [s]', row=12, col=2) fig.update_yaxes(title_text='v_vsc_q [p.u.]', row=12, col=2) + e_cap = 0.5*self.c_dc*(v_dc**2) + e_ind = 0.5*self.l_dc*(i_L**2) + fig.add_trace(go.Scatter(x=tps, y=soc, name='battery soc', mode='lines', line=dict(color='red', dash='solid')), + row=13, col=1) + fig.add_trace(go.Scatter(x=tps, y=e_cap, name='cap energy', mode='lines', line=dict(color='blue', dash='dot')), + row=13, col=1) + fig.add_trace(go.Scatter(x=tps, y=e_ind, name='ind energy', mode='lines', line=dict(color='pink', dash='dot')), + row=13, col=1) + + fig.add_trace(go.Scatter(x=tps, y=np.ones_like(soc)*self.SOC_max_pu, name="soc lim", mode='lines', line=dict(color='green', dash='dot')), + row=13, col=1) + fig.update_xaxes(title_text='Time [s]', row=13, col=1) + fig.update_yaxes(title_text='energy [p.u.]', row=13, col=1) + + duty_cycle = self.kp_i_L*(self.kp_v_dc*(v_dc_ref - v_dcf) + x1 - i_Lf + self.Kff_idc*i_dcf + self.Kff_iload*i_loadf) + x2 + duty_cycle = np.clip(duty_cycle, 0.0, 1.0) + fig.add_trace(go.Scatter(x=tps, y=duty_cycle, name="duty cycle", mode='lines', line=dict(color='red', dash='solid')), + row=13, col=2) + fig.update_xaxes(title_text='Time [s]', row=13, col=2) + fig.update_yaxes(title_text='duty cycle [p.u.]', row=13, col=2) + + fig.add_trace(go.Scatter(x=tps, y=x3, mode='lines', line=dict(color='red', dash='solid')), + row=14, col=1) + fig.update_xaxes(title_text='Time [s]', row=14, col=1) + fig.update_yaxes(title_text='x3 [p.u.]', row=14, col=1) + name = f"{self.type_}_{self.id}" fig.update_layout( title_text = name, @@ -829,9 +873,9 @@ def plot_results_emt(self, output_dir): showlegend = False, ) - fig.update_layout(height=1200*2, + fig.update_layout(height=1200*3, width=800*2, - showlegend=False, + showlegend=True, margin={'t': 0, 'l': 0, 'b': 0, 'r': 0}) fig.write_html(os.path.join(output_dir, name + ".html")) From d921a6ad28b9e452021e85ea27c529454204b00b Mon Sep 17 00:00:00 2001 From: rkravis Date: Mon, 11 May 2026 10:47:48 -0700 Subject: [PATCH 2/2] added: gfli_e + example --- .../2-bus-src-gfli_e/inputs/gfli_e.csv | 4 +- .../inputs/infinite_sources.csv | 2 +- .../2-bus-src-gfli_e/inputs/lines.csv | 2 +- .../active_power_balance_by_bus.csv | 4 +- .../outputs/ac_power_flow/bus_voltage.csv | 4 +- .../outputs/ac_power_flow/costs_summary.csv | 2 +- .../ac_power_flow/generator_dispatch.csv | 4 +- .../outputs/ac_power_flow/line_flows.csv | 2 +- .../outputs/ac_power_flow/load_shedding.csv | 4 +- .../reactive_power_balance_by_bus.csv | 4 +- .../outputs/ac_power_flow/solver_status.csv | 2 +- .../component_connection_matrices/F.csv | 4 +- .../component_connection_matrices/G.csv | 6 +- .../component_connection_matrices/L.csv | 2 +- .../2-bus-src-gfli_e/run.py | 35 +- sting/generator/gfli_e.py | 584 +++++++----------- sting/system/core.py | 2 + 17 files changed, 265 insertions(+), 402 deletions(-) diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/gfli_e.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/gfli_e.csv index 491615b..8bdc652 100755 --- a/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/gfli_e.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/gfli_e.csv @@ -1,2 +1,2 @@ -name,bus,minimum_active_power_MW,maximum_active_power_MW,minimum_reactive_power_MVAR,maximum_reactive_power_MVAR,base_power_MVA,base_voltage_kV,base_frequency_Hz,cost_variable_USDperMWh,rf1_pu,lf1_pu,rsh_pu,csh_pu,txr_power_MVA,txr_voltage1_kV,txr_voltage2_kV,txr_r1_pu,txr_l1_pu,txr_r2_pu,txr_l2_pu,beta,kp_pll,ki_pll,kp_cc,ki_cc,vdc_ref,i_load_ref,c_dc,kp_oc,ki_oc -solar,santiago,10,10,0,0,1.00E+02,4.80E-01,60,0,0.02,0.1,10,1,1.00E+02,4.80E-01,2.30E+02,0.01,0.1,0.02,0.1,0,1,10,1,10,2,0,20,1,10 \ No newline at end of file +name,bus,minimum_active_power_MW,maximum_active_power_MW,minimum_reactive_power_MVAR,maximum_reactive_power_MVAR,base_power_MVA,base_voltage_kV,base_frequency_Hz,cost_variable_USDperMWh,rf1_pu,lf1_pu,rsh_pu,csh_pu,txr_power_MVA,txr_voltage1_kV,txr_voltage2_kV,txr_r1_pu,txr_l1_pu,txr_r2_pu,txr_l2_pu,beta,kp_pll_pu,ki_pll_puHz,kp_cc_pu,ki_cc_puHz,v_dc_ref,c_dc,kp_oc_pu,ki_oc_puHz,Tload,r_dc +solar,santiago,50,50,-10,10,1.00E+02,4.80E-01,60,0,0.02,0.1,10,1,1.00E+02,4.80E-01,2.30E+02,0.01,0.1,0.02,0.1,0,1,5,1,5,1,20,0.01,0,0.01,10 \ No newline at end of file diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/infinite_sources.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/infinite_sources.csv index 9d95931..fed2eb7 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/infinite_sources.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/infinite_sources.csv @@ -1,2 +1,2 @@ name,bus,minimum_active_power_MW,maximum_active_power_MW,minimum_reactive_power_MVAR,maximum_reactive_power_MVAR,base_power_MVA,base_voltage_kV,base_frequency_Hz,cost_variable_USDperMWh,r_pu,x_pu -gen1,lima,-200,200,-500,500,1.00E+02,2.30E+02,60,0,0.01,0.5 \ No newline at end of file +gen1,lima,-200,200,-500,500,1.00E+02,2.30E+02,60,0,0.01,0.04 \ No newline at end of file diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/lines.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/lines.csv index 74a86b2..b74276c 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/lines.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/inputs/lines.csv @@ -1,2 +1,2 @@ name,from_bus,to_bus,base_power_MVA,base_voltage_kV,base_frequency_Hz,r_pu,x_pu,g_pu,b_pu -tx_1,lima,santiago,1.00E+02,2.30E+02,60,0.01,0.5,0.05,0.066666667 \ No newline at end of file +tx_1,lima,santiago,1.00E+02,2.30E+02,60,0.01,0.2,0.05,0.066666667 \ No newline at end of file diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/active_power_balance_by_bus.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/active_power_balance_by_bus.csv index bc24fde..6c7977c 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/active_power_balance_by_bus.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/active_power_balance_by_bus.csv @@ -1,3 +1,3 @@ bus,timepoint,generator_dispatch_MW,load_shedding_MW,load_MW,net_line_leaving_flow_MW -lima,timepoint_1,-0.058375056098752195,-9.974940964399896e-9,0.0,-0.05837506532163607 -santiago,timepoint_1,10.0,-9.974940964460538e-9,0.0,9.999999989460255 +lima,timepoint_1,-39.80828383129473,-9.974940963696508e-9,0.0,-39.808283840763764 +santiago,timepoint_1,50.0,-9.97494096379835e-9,0.0,49.999999989909305 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/bus_voltage.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/bus_voltage.csv index fa0fc34..66021f4 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/bus_voltage.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/bus_voltage.csv @@ -1,3 +1,3 @@ id,bus,timepoint,voltage_magnitude_pu,voltage_angle_deg -0,lima,timepoint_1,0.9795934248147871,0.0 -1,santiago,timepoint_1,1.013581804636969,1.3637928689337457 +0,lima,timepoint_1,0.9943823157326167,0.0 +1,santiago,timepoint_1,1.0045025151823652,5.136441290604731 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/costs_summary.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/costs_summary.csv index 940fe42..6ef2ea8 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/costs_summary.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/costs_summary.csv @@ -1,2 +1,2 @@ component,cost -total_cost_USD,-0.00003989976383138582 +total_cost_USD,-0.00003989976385267742 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/generator_dispatch.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/generator_dispatch.csv index 80a132f..9a20949 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/generator_dispatch.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/generator_dispatch.csv @@ -1,3 +1,3 @@ id,type,generator,timepoint,active_power_MW,reactive_power_MVAR -0,infinite_sources,gen1,timepoint_1,-0.058375056098752195,-12.902934347861217 -0,gfli_e,solar,timepoint_1,10.0,0.0 +0,infinite_sources,gen1,timepoint_1,-39.80828383129473,-7.380487609970588 +0,gfli_e,solar,timepoint_1,50.0,-1.8861486979909645 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/line_flows.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/line_flows.csv index 2ffcc27..8f4a02e 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/line_flows.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/line_flows.csv @@ -1,2 +1,2 @@ line,from_bus,to_bus,existing_capacity_MW,active_power_from_bus_MW,reactive_power_from_bus_MVAR,active_power_to_bus_MW,reactive_power_to_bus_MVAR,active_power_loss_MW,reactive_power_loss_MVAR -tx_1,lima,santiago,inf,-0.05837506532163335,-12.902934358094463,9.999999989460255,-9.95750355277473e-9,9.94162492413862,-12.902934368051966 +tx_1,lima,santiago,inf,-39.80828384076382,-7.380487617787122,49.9999999899092,-1.8861487031750395,10.191716149145378,-9.266636320962162 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/load_shedding.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/load_shedding.csv index 529532a..ffef917 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/load_shedding.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/load_shedding.csv @@ -1,3 +1,3 @@ bus,timepoint,active_load_shedding_MW,reactive_load_shedding_MVAR -lima,timepoint_1,-9.974940964399896e-9,-9.97494096436451e-9 -santiago,timepoint_1,-9.974940964460538e-9,-9.974940938160877e-9 +lima,timepoint_1,-9.974940963696508e-9,-9.974940964376057e-9 +santiago,timepoint_1,-9.97494096379835e-9,-9.974940960806504e-9 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/reactive_power_balance_by_bus.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/reactive_power_balance_by_bus.csv index 961177c..fb89795 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/reactive_power_balance_by_bus.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/reactive_power_balance_by_bus.csv @@ -1,3 +1,3 @@ bus,timepoint,generator_dispatch_MVAR,load_shedding_MVAR,load_MVAR,net_line_leaving_flow_MVAR -lima,timepoint_1,-12.902934347861217,-9.97494096436451e-9,0.0,-12.90293435809444 -santiago,timepoint_1,0.0,-9.974940938160877e-9,0.0,-9.95750355277473e-9 +lima,timepoint_1,-7.380487609970588,-9.974940964376057e-9,0.0,-7.380487617787122 +santiago,timepoint_1,-1.8861486979909645,-9.974940960806504e-9,0.0,-1.8861487031749502 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/solver_status.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/solver_status.csv index 1402c84..61ad3cd 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/solver_status.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/ac_power_flow/solver_status.csv @@ -2,4 +2,4 @@ attribute,value solver_name,ipopt solver_status,ok termination_condition,optimal -time_spent_seconds,0.10544800758361816 +time_spent_seconds,0.06075906753540039 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/F.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/F.csv index 85259ac..25ec4a0 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/F.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/F.csv @@ -3,9 +3,9 @@ Index,"('infinite_sources_0', 'i_bus_D')","('infinite_sources_0', 'i_bus_Q')","( "('infinite_sources_0', 'v_ref_q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('infinite_sources_0', 'v_bus_D')",0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0 "('infinite_sources_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0 -"('gfli_e_0', 'vdc_ref')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfli_e_0', 'v_dc_ref')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfli_e_0', 'i_load_ref')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 -"('gfli_e_0', 'q_ref')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfli_e_0', 'i_bus_q_ref')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "('gfli_e_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0 "('gfli_e_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0 "('shunt_parallel_rc_0', 'i_bus_D')",1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-1.0,0.0 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/G.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/G.csv index 1beb4b5..c46e286 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/G.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/G.csv @@ -1,11 +1,11 @@ -Index,"('infinite_sources_0', 'v_ref_d')","('infinite_sources_0', 'v_ref_q')","('gfli_e_0', 'vdc_ref')","('gfli_e_0', 'i_load_ref')","('gfli_e_0', 'q_ref')" +Index,"('infinite_sources_0', 'v_ref_d')","('infinite_sources_0', 'v_ref_q')","('gfli_e_0', 'v_dc_ref')","('gfli_e_0', 'i_load_ref')","('gfli_e_0', 'i_bus_q_ref')" "('infinite_sources_0', 'v_ref_d')",1.0,0.0,0.0,0.0,0.0 "('infinite_sources_0', 'v_ref_q')",0.0,1.0,0.0,0.0,0.0 "('infinite_sources_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0 "('infinite_sources_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0 -"('gfli_e_0', 'vdc_ref')",0.0,0.0,1.0,0.0,0.0 +"('gfli_e_0', 'v_dc_ref')",0.0,0.0,1.0,0.0,0.0 "('gfli_e_0', 'i_load_ref')",0.0,0.0,0.0,1.0,0.0 -"('gfli_e_0', 'q_ref')",0.0,0.0,0.0,0.0,1.0 +"('gfli_e_0', 'i_bus_q_ref')",0.0,0.0,0.0,0.0,1.0 "('gfli_e_0', 'v_bus_D')",0.0,0.0,0.0,0.0,0.0 "('gfli_e_0', 'v_bus_Q')",0.0,0.0,0.0,0.0,0.0 "('shunt_parallel_rc_0', 'i_bus_D')",0.0,0.0,0.0,0.0,0.0 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/L.csv b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/L.csv index e6014c3..95c81c6 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/L.csv +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/outputs/component_connection_matrices/L.csv @@ -1,4 +1,4 @@ -Index,"('infinite_sources_0', 'v_ref_d')","('infinite_sources_0', 'v_ref_q')","('gfli_e_0', 'vdc_ref')","('gfli_e_0', 'i_load_ref')","('gfli_e_0', 'q_ref')" +Index,"('infinite_sources_0', 'v_ref_d')","('infinite_sources_0', 'v_ref_q')","('gfli_e_0', 'v_dc_ref')","('gfli_e_0', 'i_load_ref')","('gfli_e_0', 'i_bus_q_ref')" "('infinite_sources_0', 'i_bus_D')",0.0,0.0,0.0,0.0,0.0 "('infinite_sources_0', 'i_bus_Q')",0.0,0.0,0.0,0.0,0.0 "('gfli_e_0', 'i_bus_D')",0.0,0.0,0.0,0.0,0.0 diff --git a/examples/small_signal_and_emt/2-bus-src-gfli_e/run.py b/examples/small_signal_and_emt/2-bus-src-gfli_e/run.py index 8dcb018..9bb1cf4 100644 --- a/examples/small_signal_and_emt/2-bus-src-gfli_e/run.py +++ b/examples/small_signal_and_emt/2-bus-src-gfli_e/run.py @@ -1,28 +1,52 @@ # Import Python standard and third-party packages from pathlib import Path - +from scipy.linalg import eig, inv +import matplotlib.pyplot as plt +import sys +import seaborn as sns +import pandas as pd +import numpy as np +import os +from plotly.subplots import make_subplots +import plotly.graph_objects as go + +sys.path.append("/Users/ruthkravis/Documents/STING") # Import sting package from sting import main from sting.system.core import System +from scipy import signal + + # Step-change input to applied to the system def step1(t): - return 0.1 if t >= 0.5 else 0.0 + return 0.2 if t >= 0.2 else 0.0 def step2(t): return 0.0 +def step3(t): + return 0.1 if t >= 1.0 else 0.0 + + +def sin_oscillation(t): + return 0.05*np.sin(2*np.pi*20*t) if t < 1 else 0 #1 Hz oscillation + +def square_oscillation(t): + osc = 0.05*signal.square(2 * np.pi * 14 * t) + return osc + inputs = { 'infinite_sources_0': { - 'v_ref_d': step2 + 'v_ref_d': step1 }, 'gfli_e_0': { - 'i_load_ref': step1 + 'i_load_ref': step2 } } -t_max = 2.0 # Simulation length (in seconds) +t_max = 1.0 # Simulation length (in seconds) # Specify path of the case study directory case_dir = Path(__file__).resolve().parent @@ -33,5 +57,6 @@ def step2(t): # Construct system and small-signal model _, ssm = main.run_ssm(case_directory=case_dir) ssm.simulate_ssm(t_max=t_max, inputs=inputs) +main.run_emt(case_directory=case_dir, inputs=inputs, t_max=t_max) print('\nok') \ No newline at end of file diff --git a/sting/generator/gfli_e.py b/sting/generator/gfli_e.py index d297fa6..26ce334 100644 --- a/sting/generator/gfli_e.py +++ b/sting/generator/gfli_e.py @@ -1,18 +1,18 @@ """ This module implements a GFLI that incorporates: - LCL filter: Two Series RL branches (one branch is the transformer) and one Parallel RC shunt. -- Outer Vdc controller +- Outer DC voltage controller +- DC-side capacitor dynamics with resistor and current source representing a load - Current controller: A dq-based frame PI controller - PLL: A basic implementation -in progress - Ruth (April 16) """ # ---------------------- # Import python packages # ---------------------- import numpy as np from dataclasses import dataclass, field -from typing import NamedTuple, Optional, ClassVar +from typing import NamedTuple, Optional import scipy.linalg # ------------------ @@ -57,9 +57,8 @@ class InitialConditionsEMT(NamedTuple): p_vsc: float v_dc: float int_vdc: float - int_q: float i_dc: float - i_load: float + i_load_ref: float class VariablesEMT(NamedTuple): @@ -84,15 +83,16 @@ class GFLIe(Generator): txr_r2_pu: float txr_l2_pu: float beta: float - kp_pll: float - ki_pll: float - kp_cc: float - ki_cc: float - vdc_ref: float # added - i_load_ref: float # added + kp_pll_pu: float + ki_pll_puHz: float + kp_cc_pu: float + ki_cc_puHz: float + v_dc_ref: float # added c_dc: float # added - kp_oc: float # added - ki_oc: float # added + kp_oc_pu: float # added + ki_oc_puHz: float # added + Tload: float # added + r_dc: float # added x_pll_rescale: np.ndarray = field(default_factory=lambda: np.array([[100, 0], [0, 1]])) name: str = field(default_factory=str) emt_init: Optional[InitialConditionsEMT] = None @@ -113,7 +113,7 @@ def wbase(self): def _build_small_signal_model(self): # Current PI controller - kp_cc, ki_cc = self.kp_cc, self.ki_cc + kp_cc, ki_cc = self.kp_cc_pu, self.ki_cc_puHz pi_cc_d, pi_cc_q = self.emt_init.pi_cc_d, self.emt_init.pi_cc_q pi_controller = StateSpaceModel( A = np.zeros((2,2)), @@ -153,7 +153,7 @@ def _build_small_signal_model(self): y = DynamicalVariables(name=["i_vsc_d", "i_vsc_q", "i_bus_d", "i_bus_q", "v_lcl_sh_d", "v_lcl_sh_q"])) # Phase-locked loop - kp_pll, ki_pll = self.kp_pll, self.ki_pll + kp_pll, ki_pll = self.kp_pll_pu, self.ki_pll_puHz beta = self.beta vmag_bus = self.emt_init.vmag_bus sinphi = np.sin(self.emt_init.angle_ref*np.pi/180) @@ -181,77 +181,75 @@ def _build_small_signal_model(self): pll.C = pll.C @ scipy.linalg.inv(self.x_pll_rescale) # Outer control + DC capacitor dynamics - Kp, Ki, Cdc = self.kp_oc, self.ki_oc, self.c_dc - r_dc = 100 - outer_control = StateSpaceModel(A = np.array([[0, 0, Ki], - [0, 0, 0], - [0, 0, -1/r_dc]]), - B = np.array([[-Ki, 0, 0, 0, 0], - [0, 0, -Ki, Ki, 0], - [0, wb/Cdc, 0, 0, -wb/Cdc]]), - C = np.array([[1, 0, Kp], - [0, 1, 0], - [0, 0, 1]]), - D = np.array([[-Kp, 0, 0, 0, 0], - [0, 0, -Kp, Kp, 0], - [0, 0, 0, 0, 0]]), - u = DynamicalVariables(name=["vdc_ref", "i_load_ref", "q_ref", "q", "idc"]), - y = DynamicalVariables(name=["i_bus_d_ref", "i_bus_q_ref", "v_dc"]), - x = DynamicalVariables(name=["int_vdc", "int_q", "v_dc"], - init=[self.emt_init.int_vdc, self.emt_init.int_q, self.emt_init.v_dc])) + Kp, Ki, Cdc, Tload, r_dc = self.kp_oc_pu, self.ki_oc_puHz, self.c_dc, self.Tload, self.r_dc + outer_control = StateSpaceModel(A = np.array([[0, Ki, 0], + [0, -1/r_dc, -wb/Cdc], + [0, 0, -1/Tload]]), + B = np.array([[-Ki, 0, 0], + [0, -wb/Cdc, -wb/Cdc], + [0, 1/Tload, 0]]), + C = np.array([[1, Kp, 0], + [0, 1, 0]]), + D = np.array([[-Kp, 0, 0], + [0, 0, 0]]), + u = DynamicalVariables(name=["v_dc_ref", "i_load_ref", "idc"]), + y = DynamicalVariables(name=["i_bus_d_ref", "v_dc"]), + x = DynamicalVariables(name=["int_vdc", "v_dc", "i_load"], + init=[self.emt_init.int_vdc, self.emt_init.v_dc, self.emt_init.i_load_ref])) # Construction of CCM matrices # ustack = F*ystack + G*u - # ustack = i2cdq, v1cdq, v2cdq, w, v2cdq, vdcref, iload, qref, q, idc (14) - # y_stack = vmd, vmq, i2d, i2q, i1d, i1q, v3d, v3q, theta, w, idref, iqref, vdc (13) - extra 4 + 3 = 7 - # u = vdcref, iload, qref, v2d, v2q + # ustack = i2dq_c, v1dq_c, v2dq_c, w, v2dq, vdcref, iload_ref, idc (12) + # y_stack = e1d, e1q, i1d_c, i1q_c, i2d_c, i2q_c, v3d_c, v3q_c, theta, w, i2d_ref, vdc (12) + # u = vdc_ref, iload_ref, i2q_ref, v2d, v2q # y = i2dq - # reactive power linearization coefficients - a1 = -self.emt_init.v_lcl_sh_d - a2 = -self.emt_init.i_bus_q - a3 = self.emt_init.v_lcl_sh_q - a4 = self.emt_init.i_bus_d - # dc power balance linearization - b1 = self.emt_init.v_vsc_d/self.emt_init.v_dc - b2 = self.emt_init.i_vsc_d/self.emt_init.v_dc - b3 = self.emt_init.v_vsc_q/self.emt_init.v_dc # is this just 0 ? - b4 = self.emt_init.i_vsc_q/self.emt_init.v_dc - b5 = - self.emt_init.i_dc/self.emt_init.v_dc + v_dc = self.emt_init.v_dc + + b1 = self.emt_init.v_vsc_d/v_dc # i1d + b2 = self.emt_init.i_vsc_d/v_dc #e1d + b3 = - (self.emt_init.i_vsc_d/v_dc)*(self.lf1_pu+self.lf2_pu) #i2q + b4 = self.emt_init.v_vsc_q/v_dc # i1q + b5 = self.emt_init.i_vsc_q/v_dc # e1q + b6 = (self.emt_init.i_vsc_q/v_dc)*(self.lf1_pu+self.lf2_pu) #i2d + b7 = - self.emt_init.i_dc/v_dc #vdc + b8 = -(self.emt_init.i_vsc_q/v_dc)*self.beta*vmag_bus # theta # Construction of CCM matrices - Fccm = np.vstack( ( np.hstack((np.zeros((10, )), 1, 0, 0)) ,# i2ref_d - np.hstack((np.zeros((10, )), 0, 1, 0)) , # i2ref_q - np.hstack((np.zeros((2,4)), np.eye(2) ,np.zeros((2,7)))), # i2c_dq - [1, 0, 0, 0, 0, -(lf1+lf2), 0, 0, 0, 0, 0, 0, 0], # v1c_d - [0, 1, 0, 0, (lf1+lf2), 0, 0, 0, -beta*vmag_bus, 0, 0, 0, 0], # v1c_q - np.zeros((13, )) , # v2c_d - np.append( np.zeros((8,)) , [-vmag_bus, 0, 0, 0, 0] ), # v2c_q - np.append( np.zeros((9,)) , [1, 0, 0, 0] ), # w - np.zeros((2, 13)), # v2c_dq - np.zeros((3, 13)), #vdcref, iload, qref - np.hstack((np.zeros(4,), [a3, a1, a2, a4], np.zeros(5,))), # q - np.hstack(([b2, b4, b1, b3], np.zeros(8,), [b5])) #idc + Fccm = np.vstack( ( np.hstack((np.zeros((10, )), 1, 0)) ,# i2d_ref + np.zeros((12,)), # i2q_ref + np.hstack((np.zeros((2,4)), np.eye(2) ,np.zeros((2,6)))), # i2dq_c + [1, 0, 0, 0, 0, -(lf1+lf2), 0, 0, 0, 0, 0, 0], # v1d_c + [0, 1, 0, 0, (lf1+lf2), 0, 0, 0, -beta*vmag_bus, 0, 0, 0], # v1q_c + np.zeros((12, )) , # v2d_c + np.append( np.zeros((8,)) , [-vmag_bus, 0, 0, 0] ), # v2q_c + np.append( np.zeros((9,)) , [1, 0, 0] ), # w + np.zeros((2, 12)), # v2_dq + np.zeros((2, 12)), #vdc_ref, iload_ref + [b2, b5, b1, b4, b6, b3, 0, 0, b8, 0, 0, b7] #idc ) ) - Gccm = np.vstack(( np.zeros((4, 5)), # i2ref_dq, i2c_dq, - [0, 0, 0, beta*cosphi , beta*sinphi], # v1c_d - [0, 0, 0, -beta*sinphi, beta*cosphi], # v1c_q - [0, 0, 0, cosphi ,sinphi], # v2c_d - [0, 0, 0, -sinphi ,cosphi], # v2c_q + Gccm = np.vstack(( np.zeros(5,), # i2ref_d, + [0, 0, 1, 0, 0], #i2q_ref + np.zeros((2,5)), #i2dq_c, + [0, 0, 0, beta*cosphi , beta*sinphi], # v1d_c + [0, 0, 0, -beta*sinphi, beta*cosphi], # v1q_c + [0, 0, 0, cosphi ,sinphi], # v2d_c + [0, 0, 0, -sinphi ,cosphi], # v2q_c np.zeros((5, )), # w np.hstack((np.zeros((2,3)), np.eye(2) ) ), # v2dq - np.hstack((np.eye(3), np.zeros((3,2)))), # vdc_ref, iload, q_ref - np.zeros((2,5)) # q, idc + [1, 0, 0, 0, 0], #vdc_ref + [0, 1, 0, 0, 0], #iload_ref + np.zeros((1,5)) # idc ) ) - Hccm = np.vstack(( [ 0, 0 , 0, 0, cosphi , -sinphi, 0, 0, -sinphi*i_bus_d-cosphi*i_bus_q, 0, 0, 0, 0], - [0, 0, 0, 0, sinphi , cosphi , 0, 0, cosphi*i_bus_d-sinphi*i_bus_q, 0, 0, 0, 0] )) + Hccm = np.vstack(( [ 0, 0 , 0, 0, cosphi , -sinphi, 0, 0, -sinphi*i_bus_d-cosphi*i_bus_q, 0, 0, 0], + [0, 0, 0, 0, sinphi , cosphi , 0, 0, cosphi*i_bus_d-sinphi*i_bus_q, 0, 0, 0] )) Lccm = np.zeros((2, 5)) @@ -261,9 +259,9 @@ def _build_small_signal_model(self): # Inputs and outputs v_bus_D, v_bus_Q= self.emt_init.v_bus_D, self.emt_init.v_bus_Q u = DynamicalVariables( - name=["vdc_ref", "i_load_ref", "q_ref", "v_bus_D", "v_bus_Q"], + name=["v_dc_ref", "i_load_ref", "i_bus_q_ref", "v_bus_D", "v_bus_Q"], type=["device", "device", "device", "grid", "grid"], - init=[self.vdc_ref, self.emt_init.i_dc, self.emt_init.q_bus, v_bus_D, v_bus_Q]) + init=[self.emt_init.v_dc, self.emt_init.i_load_ref, self.emt_init.i_bus_q, v_bus_D, v_bus_Q]) i_bus_D, i_bus_Q= self.emt_init.i_bus_D, self.emt_init.i_bus_Q y = DynamicalVariables( @@ -316,13 +314,11 @@ def _calculate_emt_initial_conditions(self): v_vsc_dq - self.beta * v_bus_dq - 1j * (self.lf1_pu + self.lf2_pu) * i_bus_dq ) - - # Initial conditions for outer control / dc - # DC-side initial conditions - v_dc = self.vdc_ref + v_dc = self.v_dc_ref p_vsc = (v_vsc_dq*np.conjugate(i_vsc_dq)).real # power at converter terminals i_dc = p_vsc/v_dc + i_load = -v_dc/self.r_dc - i_dc self.emt_init = InitialConditionsEMT( vmag_bus=vmag_bus, @@ -348,37 +344,49 @@ def _calculate_emt_initial_conditions(self): p_vsc=p_vsc, i_dc=i_dc, int_vdc=i_bus_dq.real, - int_q=i_bus_dq.imag, - i_load=i_dc, + i_load_ref=i_load, v_vsc_d=v_vsc_dq.real, v_vsc_q=v_vsc_dq.imag - ) def define_variables_emt(self): # States # ------ - + # Initial conditions + angle_ref = self.emt_init.angle_ref + pi_cc_d, pi_cc_q = self.emt_init.pi_cc_d, self.emt_init.pi_cc_q + + # these quantities are already in the converter ref frame (defined by angle_ref) + i_bus_d, i_bus_q = self.emt_init.i_bus_d, self.emt_init.i_bus_q + i_vsc_d, i_vsc_q = self.emt_init.i_vsc_d, self.emt_init.i_vsc_q + v_sh_d, v_sh_q = self.emt_init.v_lcl_sh_d, self.emt_init.v_lcl_sh_q + # convert to abc + i_bus_a, i_bus_b, i_bus_c = dq02abc(i_bus_d, i_bus_q, 0, angle_ref*np.pi/180) + i_vsc_a, i_vsc_b, i_vsc_c = dq02abc(i_vsc_d, i_vsc_q, 0, angle_ref*np.pi/180) + v_sh_a, v_sh_b, v_sh_c = dq02abc(v_sh_d, v_sh_q, 0, angle_ref*np.pi/180) + x = DynamicalVariables( - name = [], + name = ['pi_cc_d', 'pi_cc_q', 'theta_pll', 'gamma_pll', "i_vsc_a", "i_vsc_b", "i_vsc_c", "v_sh_a", "v_sh_b","v_sh_c", "i_bus_a", "i_bus_b", "i_bus_c", "int_vdc", "v_dc", "i_load"], component = f"{self.type_}_{self.id}", - init=[] + init = [pi_cc_d, pi_cc_q, angle_ref * np.pi/180, 0, i_vsc_a, i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c, self.emt_init.int_vdc, self.emt_init.v_dc, self.emt_init.i_load_ref] ) - + # Inputs # ------ # Initial conditions + v_bus_D, v_bus_Q = self.emt_init.v_bus_D, self.emt_init.v_bus_Q + v_bus_a, v_bus_b, v_bus_c = dq02abc(v_bus_D, v_bus_Q, 0, 0) u = DynamicalVariables( - name=["vdc_ref", "iload", "q_ref", "v_bus_a", "v_bus_b", "v_bus_c"], + name=["v_dc_ref", "i_load_ref", "i_bus_q_ref", "v_bus_a", "v_bus_b", "v_bus_c"], component=f"{self.type_}_{self.id}", - type=["device", "device", "device", "grid", "grid"], - init=[] + type=["device", "device", "device", "grid", "grid", "grid"], + init=[self.emt_init.v_dc, self.emt_init.i_load_ref, self.emt_init.i_bus_q, v_bus_a, v_bus_b, v_bus_c] ) - + # Outputs # ------- @@ -389,89 +397,88 @@ def define_variables_emt(self): ) self.variables_emt = VariablesEMT(x=x,u=u,y=y) - - + def get_derivative_state_emt(self): - - # Get state values - # outer control / current control / lcl / pll - angle_pc, w_pc, p_pc, q_pc, gamma, i_vsc_a, i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c, i_Lf, v_dcf, i_dcf, i_loadf, x1, x2, i_L, v_dc, i_load, soc, x3 = self.variables_emt.x.value + """ + It returns a vector with the differential equations that describe the dynamics of the GFLI. + This model includes: pi controller, pll, and LCL filter. + """ + # Get state values # here in progress + pi_cc_d, pi_cc_q, theta_pll, gamma_pll, i_vsc_a, i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c, int_vdc, v_dc, i_load = self.variables_emt.x.value # Get input values (external inputs) - vdc_ref, iload, qref, v_bus_a, v_bus_b, v_bus_c = self.variables_emt.u.value - - # convert relevant quantities to dq (ibr frame) - v_sh_d, v_sh_q, _ = abc2dq0(v_sh_a, v_sh_b, v_sh_c, angle_pc) # for power controller - i_bus_d, i_bus_q, _ = abc2dq0(i_bus_a, i_bus_b, i_bus_c, angle_pc) # for power controller - i_vsc_d, i_vsc_q, _ = abc2dq0(i_vsc_a, i_vsc_b, i_vsc_c, angle_pc) + v_dc_ref, i_load_ref, i_bus_q_ref, v_bus_a, v_bus_b, v_bus_c = self.variables_emt.u.value - # outer control - id_ref = int_vdc + self.kp_oc*(vdc_ref - v_dc) - iq_ref = int_q + self.kp_oc*(qref - q) - - # current controller - vmd = self.ki_cc*gamma_d + self.kp_cc*(id_ref - i_d) - vmq = self.ki_cc*gamma_q + self.kp_cc*(id_ref - i_d) - - # PLL - + # convert relevant quantities to dq + v_bus_d, v_bus_q, _ = abc2dq0(v_bus_a, v_bus_b, v_bus_c, theta_pll) + i_bus_d, i_bus_q, _ = abc2dq0(i_bus_a, i_bus_b, i_bus_c, theta_pll) + + # Update algebraic states - # Do Q-V droop - v_sh_mag_ref = v_ref - self.droop_q_pu*(q_pc - q_ref) # adjusting voltage reference based on reactive power error (measured at capacitor) + # outer loop Vdc control + i_bus_d_ref = self.kp_oc_pu*(-v_dc_ref + v_dc) + int_vdc - # NB updating algebraic states! - # Updating converter terminal voltages - v_vsc_d = gamma + self.kp_vc_pu*(v_sh_mag_ref - (v_sh_d**2 + v_sh_q**2)**0.5) # update - v_vsc_q = 0.0 # update + # current controller output + e_d = pi_cc_d + self.kp_cc_pu * (i_bus_d_ref - i_bus_d) + e_q = pi_cc_q + self.kp_cc_pu * (i_bus_q_ref - i_bus_q) - # # check magnitude wrt v_dc and limit if necessary - # if v_vsc_d > v_dc: # can check only d component because v_vsc_q= 0 - # v_vsc_d = v_dc + v_vsc_d = e_d + self.beta * v_bus_d - (self.lf1_pu + self.lf2_pu) * i_bus_q + v_vsc_q = e_q + self.beta * v_bus_q + (self.lf1_pu + self.lf2_pu) * i_bus_d - # convert to abc to feed into filter dynamics - v_vsc_a, v_vsc_b, v_vsc_c = dq02abc(v_vsc_d, v_vsc_q, 0, angle_pc) # correct to use this angle? - - # DC/AC power balance + # calculate idc + i_vsc_d, i_vsc_q, _ = abc2dq0(i_vsc_a, i_vsc_b, i_vsc_c, theta_pll) i_dc = (v_vsc_d*i_vsc_d + v_vsc_q*i_vsc_q)/v_dc - - - - # Differential equations - # ---------------------- - - # Power controller: - def outer_loop_dynamics(y, internal_inputs): + + # convert to abc to feed into filter dynamics + v_vsc_a, v_vsc_b, v_vsc_c = dq02abc(v_vsc_d, v_vsc_q, 0, theta_pll) + + def current_controller_dynamics(y, internal_inputs): """ - PI control of Vdc error to generate id_ref - PI control of Q error to generate iq_ref + It returns the differential equations that describe the dynamics of the current controller. + The current controller has: virtual inertia, filter for active and reactive power. """ - int_vdc, int_q, v_dc = y[0], y[1], y[2] - - vdc_ref, iload, qref, idc, q = internal_inputs + + # Definition of states for the ODEs of the current controller + pi_cc_d, pi_cc_q = y[0], y[1] + + # Extract the list of parameters + kp_cc = self.kp_cc_pu # proportional gain of current controller + ki_cc = self.ki_cc_puHz # integral gain of current controller + + # Define internal inputs for the current controller at timepoint "t" + i_bus_d_ref, i_bus_q_ref, i_bus_d, i_bus_q = internal_inputs + + # Define ODEs that describe the dynamics of the current controller + d_pi_cc_d = ki_cc * (i_bus_d_ref - i_bus_d) + d_pi_cc_q = ki_cc * (i_bus_q_ref - i_bus_q) - d_int_vdc = self.Ki_oc*(v_dc_ref - v_dc) - d_int_q = self.Ki_oc*(qref - q) - d_v_dc = (-self.wbase/self.cdc)*(idc - iload) + return [d_pi_cc_d, d_pi_cc_q] - return [d_int_vdc, d_int_q, d_v_dc] - - - def current_controller_dynamics(y, internal_inputs): + def pll_dynamics(y, internal_inputs): """ - decoupled PI controllers + It returns the differential equations that describe the dynamics of the PLL. + The PLL tracks the phase of the grid voltage. """ - gamma = y[0] - - id_ref, iq_ref, id, iq = internal_inputs - - d_gamma_d = id_ref - id - d_gamma_q = iq_ref - iq + # Definition of states for the ODEs of the pll + theta_pll, gamma_pll = y[0], y[1] + + # Extract the list of parameters + kp_pll = self.kp_pll_pu # proportional gain of PLL + ki_pll = self.ki_pll_puHz # integral gain of PLL + w_base = self.wbase # base frequency of the system + + # Define voltage at bus + v_bus_q = internal_inputs + + # Define ODEs that describe the dynamics of the PLL + d_theta_pll = kp_pll * v_bus_q * w_base + gamma_pll + w_base + d_gamma_pll = ki_pll * v_bus_q + + return [d_theta_pll, d_gamma_pll] - return [d_gamma_d, d_gamma_q] - - def lcl_filter_dynamics(y, internal_inputs): """ + It returns the differential equations that describe the dynamics of the LCL filter. The LCL filter connects the VSC to the grid. It has three branches: the first branch (RL) connects the VSC to the shunt element, the second branch is the shunt element (RC), and the third branch (RL) connects the shunt element to the grid. @@ -483,258 +490,87 @@ def lcl_filter_dynamics(y, internal_inputs): i_bus_a, i_bus_b, i_bus_c = y[6], y[7], y[8] # currents flowing to bus # Extract the list of parameters - rf1, xf1, rf2, xf2, rsh, csh = self.rf1_pu, self.xf1_pu, self.rf2_pu, self.xf2_pu, self.rsh_pu, self.csh_pu - wb = self.wbase - r1 = rf1 - r2 = rf2 - x1 = xf1 - x2 = xf2 - - # Inputs + r1 = self.rf1_pu # resistance [p.u.] of first branch of filter + l1 = self.lf1_pu # inductance [p.u.] of first branch of filter + r2 = self.rf2_pu # resistance [p.u.] of second branch of filter + l2 = self.lf2_pu # inductance [p.u.] of second branch of filter + rsh = self.rsh_pu # resistance [p.u.] of series RC shunt + csh = self.csh_pu # capacitance [p.u.] of series RC shunt + wb = self.wbase # nominal frequency of the system + + # Define voltage at vsc at timepoint "t" v_vsc_a, v_vsc_b, v_vsc_c, v_bus_a, v_bus_b, v_bus_c = internal_inputs # Define ODEs that describe the dynamics of the LCL filter - di_vsc_a = wb/x1 *(v_vsc_a - v_sh_a - r1 * i_vsc_a) - di_vsc_b = wb/x1 *(v_vsc_b - v_sh_b - r1 * i_vsc_b) - di_vsc_c = wb/x1 *(v_vsc_c - v_sh_c - r1 * i_vsc_c) + di_vsc_a = wb/l1 *(v_vsc_a - v_sh_a - r1 * i_vsc_a) + di_vsc_b = wb/l1 *(v_vsc_b - v_sh_b - r1 * i_vsc_b) + di_vsc_c = wb/l1 *(v_vsc_c - v_sh_c - r1 * i_vsc_c) dv_sh_a = wb/csh * (-v_sh_a/rsh + i_vsc_a - i_bus_a) dv_sh_b = wb/csh * (-v_sh_b/rsh + i_vsc_b - i_bus_b) dv_sh_c = wb/csh * (-v_sh_c/rsh + i_vsc_c - i_bus_c) - di_bus_a = wb/x2 *(v_sh_a - v_bus_a - r2 * i_bus_a) - di_bus_b = wb/x2 *(v_sh_b - v_bus_b - r2 * i_bus_b) - di_bus_c = wb/x2 *(v_sh_c - v_bus_c - r2 * i_bus_c) + di_bus_a = wb/l2 *(v_sh_a - v_bus_a - r2 * i_bus_a) + di_bus_b = wb/l2 *(v_sh_b - v_bus_b - r2 * i_bus_b) + di_bus_c = wb/l2 *(v_sh_c - v_bus_c - r2 * i_bus_c) return [di_vsc_a, di_vsc_b, di_vsc_c, dv_sh_a, dv_sh_b, dv_sh_c, di_bus_a, di_bus_b, di_bus_c] - - - def pll_dynamics(y, internal_inputs): - """ - """ - - int_pll, theta = y[0], y[1] + + def outer_loop_and_dc_side(y, internal_inputs): + int_vdc, v_dc, i_load = y[0], y[1], y[2] - v_bus_q = internal_inputs - - d_int_pll = self.ki_pll*(v_bus_q) - d_theta = self.wbase*self.ki_pll*int_pll - self.wbase*vm*self.kp_pll*theta + v_dc_ref, i_load_ref, i_dc = internal_inputs - return [d_int_pll, d_theta] - + d_int_vdc = self.ki_oc_puHz*(-v_dc_ref + v_dc) + d_vdc = (self.wbase/self.c_dc)*(-i_load - v_dc/self.r_dc - i_dc) + d_iload = 1/(self.Tload)*(i_load_ref - i_load) + + return [d_int_vdc, d_vdc, d_iload] - dy_pc = outer_loop_dynamics([angle_pc, w_pc, p_pc, q_pc], [v_sh_d, v_sh_q, i_bus_d, i_bus_q, p_ref]) - dy_vc = current_controller_dynamics([gamma], [v_sh_mag_ref, v_sh_d, v_sh_q]) - dy_lcl = lcl_filter_dynamics([i_vsc_a , i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c], [v_vsc_a, v_vsc_b, v_vsc_c, v_bus_a, v_bus_b, v_bus_c]) - dy_pll = pll_dynamics([int_pll, theta], [v_sh_a, v_sh_b, v_sh_c]) + d_pi_cc_d, d_pi_cc_q = current_controller_dynamics([pi_cc_d, pi_cc_q], [i_bus_d_ref, i_bus_q_ref, i_bus_d, i_bus_q]) + + d_theta_pll, d_gamma_pll = pll_dynamics([theta_pll, gamma_pll], v_bus_q) - return np.hstack([dy_pc, dy_vc, dy_lcl]) + di_vsc_a, di_vsc_b, di_vsc_c, dv_sh_a, dv_sh_b, dv_sh_c, di_bus_a, di_bus_b, di_bus_c = lcl_filter_dynamics([i_vsc_a , i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c], [v_vsc_a, v_vsc_b, v_vsc_c, v_bus_a, v_bus_b, v_bus_c]) + d_int_vdc, d_vdc, d_iload = outer_loop_and_dc_side([int_vdc, v_dc, i_load], [v_dc_ref, i_load_ref, i_dc]) + return [d_pi_cc_d, d_pi_cc_q, d_theta_pll, d_gamma_pll, di_vsc_a, di_vsc_b, di_vsc_c, dv_sh_a, dv_sh_b, dv_sh_c, di_bus_a, di_bus_b, di_bus_c, d_int_vdc, d_vdc, d_iload] + def get_output_emt(self): - # Output is i_bus_abc - angle_pc, w_pc, p_pc, q_pc, gamma, i_vsc_a, i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c, i_Lf, v_dcf, i_dcf, i_loadf, x1, x2, i_L, v_dc, i_load, soc, x3 = self.variables_emt.x.value - + pi_cc_d, pi_cc_q, theta_pll, gamma_pll, i_vsc_a, i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c, int_vdc, v_dc, i_load = self.variables_emt.x.value return [i_bus_a, i_bus_b, i_bus_c] - def plot_results_emt(self, output_dir): - - angle_pc, w_pc, p_pc, q_pc, gamma, i_vsc_a, i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c, i_Lf, v_dcf, i_dcf, i_loadf, x1, x2, i_L, v_dc, i_load, soc, x3 = self.variables_emt.x.value - - #i_L = np.clip(i_L, -1000.0, 1.0) + def plot_results_emt(self) -> DynamicalVariables: + """ + Plot EMT simulation results + """ + + pi_cc_d, pi_cc_q, theta_pll, gamma_pll, i_vsc_a, i_vsc_b, i_vsc_c, v_sh_a, v_sh_b, v_sh_c, i_bus_a, i_bus_b, i_bus_c, int_vdc, v_dc, i_load = self.variables_emt.x.value tps = self.variables_emt.x.time # Transform abc to dq0 - i_vsc_d, i_vsc_q, _ = zip(*[abc2dq0(a, b, c, ang) for a, b, c, ang in zip(i_vsc_a, i_vsc_b, i_vsc_c, angle_pc)]) - v_sh_d, v_sh_q, _ = zip(*[abc2dq0(a, b, c, ang) for a, b, c, ang in zip(v_sh_a, v_sh_b, v_sh_c, angle_pc)]) - i_bus_d, i_bus_q, _ = zip(*[abc2dq0(a, b, c, ang) for a, b, c, ang in zip(i_bus_a, i_bus_b, i_bus_c, angle_pc)]) + i_vsc_d, i_vsc_q, _ = zip(*[abc2dq0(a, b, c, ang) for a, b, c, ang in zip(i_vsc_a, i_vsc_b, i_vsc_c, theta_pll)]) + v_sh_d, v_sh_q, _ = zip(*[abc2dq0(a, b, c, ang) for a, b, c, ang in zip(v_sh_a, v_sh_b, v_sh_c, theta_pll)]) + i_bus_d, i_bus_q, _ = zip(*[abc2dq0(a, b, c, ang) for a, b, c, ang in zip(i_bus_a, i_bus_b, i_bus_c, theta_pll)]) - # calculate v_vsc v_sh_dq = v_sh_d + np.multiply(v_sh_q, 1j) i_vsc_dq = i_vsc_d + np.multiply(i_vsc_q, 1j) - v_vsc_dq = v_sh_dq + np.multiply((self.rf1_pu + self.xf1_pu * 1j), i_vsc_dq) - - fig = make_subplots( - rows=14, cols=2, - horizontal_spacing=0.15, - vertical_spacing=0.05, - ) - - fig.add_trace(go.Scatter(x=tps, y=w_pc, mode='lines', line=dict(color='red', dash='solid')), - row=1, col=1) - fig.update_xaxes(title_text='Time [s]', row=1, col=1) - fig.update_yaxes(title_text='Frequency pc [p.u.]', row=1, col=1) - - fig.add_trace(go.Scatter(x=tps, y=angle_pc * 180 / np.pi, mode='lines', line=dict(color='red', dash='solid')), - row=1, col=2) - fig.update_xaxes(title_text='Time [s]', row=1, col=2) - fig.update_yaxes(title_text='Angle pc [deg]', row=1, col=2) - - fig.add_trace(go.Scatter(x=tps, y=p_pc, name="p_pc", mode='lines', line=dict(color='red', dash='solid')), - row=2, col=1) - fig.update_xaxes(title_text='Time [s]', row=2, col=1) - fig.update_yaxes(title_text='Active Power pc [p.u.]', row=2, col=1) - - fig.add_trace(go.Scatter(x=tps, y=q_pc, mode='lines', line=dict(color='red', dash='solid')), - row=2, col=2) - fig.update_xaxes(title_text='Time [s]', row=2, col=2) - fig.update_yaxes(title_text='Reactive Power pc [p.u.]', row=2, col=2) - - fig.add_trace(go.Scatter(x=tps, y=gamma, mode='lines', line=dict(color='red', dash='solid')), - row=3, col=1) - fig.update_xaxes(title_text='Time [s]', row=3, col=1) - fig.update_yaxes(title_text='Gamma [p.u.]', row=3, col=1) - - fig.add_trace(go.Scatter(x=tps, y=i_loadf, mode='lines', line=dict(color='red', dash='solid')), - row=3, col=2) - fig.update_xaxes(title_text='Time [s]', row=3, col=2) - fig.update_yaxes(title_text='iload_f [p.u.]', row=3, col=2) - - fig.add_trace(go.Scatter(x=tps, y=i_vsc_d, mode='lines', line=dict(color='red', dash='solid')), - row=4, col=1) - fig.update_xaxes(title_text='Time [s]', row=4, col=1) - fig.update_yaxes(title_text='i_vsc_d [p.u.]', row=4, col=1) - - fig.add_trace(go.Scatter(x=tps, y=i_vsc_q, mode='lines', line=dict(color='red', dash='solid')), - row=4, col=2) - fig.update_xaxes(title_text='Time [s]', row=4, col=2) - fig.update_yaxes(title_text='i_vsc_q [p.u.]', row=4, col=2) - - fig.add_trace(go.Scatter(x=tps, y=v_sh_d, mode='lines', line=dict(color='red', dash='solid')), - row=5, col=1) - fig.update_xaxes(title_text='Time [s]', row=5, col=1) - fig.update_yaxes(title_text='v_sh_d [p.u.]', row=5, col=1) - - fig.add_trace(go.Scatter(x=tps, y=v_sh_q, mode='lines', line=dict(color='red', dash='solid')), - row=5, col=2) - fig.update_xaxes(title_text='Time [s]', row=5, col=2) - fig.update_yaxes(title_text='v_sh_q [p.u.]', row=5, col=2) - - fig.add_trace(go.Scatter(x=tps, y=i_bus_d, mode='lines', line=dict(color='red', dash='solid')), - row=6, col=1) - fig.update_xaxes(title_text='Time [s]', row=6, col=1) - fig.update_yaxes(title_text='i_bus_d [p.u.]', row=6, col=1) - - fig.add_trace(go.Scatter(x=tps, y=i_bus_q, mode='lines', line=dict(color='red', dash='solid')), - row=6, col=2) - fig.update_xaxes(title_text='Time [s]', row=6, col=2) - fig.update_yaxes(title_text='i_bus_q [p.u.]', row=6, col=2) - - fig.add_trace(go.Scatter(x=tps, y=v_dc, mode='lines', line=dict(color='red', dash='solid')), - row=7, col=1) - fig.update_xaxes(title_text='Time [s]', row=7, col=1) - fig.update_yaxes(title_text='v_dc [p.u.]', row=7, col=1) - - fig.add_trace(go.Scatter(x=tps, y=i_L, mode='lines', line=dict(color='red', dash='solid')), - row=7, col=2) - fig.update_xaxes(title_text='Time [s]', row=7, col=2) - fig.update_yaxes(title_text='i_L [p.u.]', row=7, col=2) - - - fig.add_trace(go.Scatter(x=tps, y=v_dcf, mode='lines', line=dict(color='red', dash='solid')), - row=8, col=1) - fig.update_xaxes(title_text='Time [s]', row=8, col=1) - fig.update_yaxes(title_text='v_dcf [p.u.]', row=8, col=1) - - fig.add_trace(go.Scatter(x=tps, y=i_Lf, mode='lines', line=dict(color='red', dash='solid')), - row=8, col=2) - fig.update_xaxes(title_text='Time [s]', row=8, col=2) - fig.update_yaxes(title_text='i_Lf [p.u.]', row=8, col=2) - - - fig.add_trace(go.Scatter(x=tps, y=i_dcf, mode='lines', line=dict(color='red', dash='solid')), - row=9, col=1) - fig.update_xaxes(title_text='Time [s]', row=9, col=1) - fig.update_yaxes(title_text='i_dcf [p.u.]', row=9, col=1) - - fig.add_trace(go.Scatter(x=tps, y=x1, mode='lines', line=dict(color='red', dash='solid')), - row=9, col=2) - fig.update_xaxes(title_text='Time [s]', row=9, col=2) - fig.update_yaxes(title_text='x1 [p.u.]', row=9, col=2) - - fig.add_trace(go.Scatter(x=tps, y=x2, mode='lines', line=dict(color='red', dash='solid')), - row=10, col=1) - fig.update_xaxes(title_text='Time [s]', row=10, col=1) - fig.update_yaxes(title_text='x2 [p.u.]', row=10, col=1) - - fig.add_trace(go.Scatter(x=tps, y=i_load, mode='lines', line=dict(color='red', dash='solid')), - row=10, col=2) - fig.update_xaxes(title_text='Time [s]', row=10, col=2) - fig.update_yaxes(title_text='i_load [p.u.]', row=10, col=2) - - # power comparisons (calculated) + i_bus_dq = i_bus_d + np.multiply(i_bus_q, 1j) + v_vsc_dq = v_sh_dq + np.multiply((self.rf1_pu + self.lf1_pu * 1j), i_vsc_dq) p_vsc = (v_vsc_dq*np.conjugate(i_vsc_dq)).real - p_load = i_load*v_dc - p_ref, q_ref, v_ref, v_dc_ref, v_s, i_load_ref, v_bus_a, v_bus_b, v_bus_c = self.variables_emt.u.value - p_bat = i_L*v_s - p_capacitor = p_vsc + p_load - p_bat - fig.add_trace(go.Scatter(x=tps, y=p_vsc, name="p_vsc", mode='lines', line=dict(color='red', dash='solid')), - row=11, col=1) - fig.add_trace(go.Scatter(x=tps, y=p_load, name="p_load", mode='lines', line=dict(color='blue', dash='solid')), - row=11, col=1) - fig.add_trace(go.Scatter(x=tps, y=p_bat, name="p_bat", mode='lines', line=dict(color='green', dash='solid')), - row=11, col=1) - fig.add_trace(go.Scatter(x=tps, y=p_capacitor, name="p_cap", mode='lines', line=dict(color='pink', dash='solid')), - row=11, col=1) - - fig.add_trace(go.Scatter(x=tps, y=np.ones_like(p_bat)*self.Pbat_max_pu, name="p_bat_lim", mode='lines', line=dict(color='green', dash='dot')), - row=11, col=1) - fig.update_xaxes(title_text='Time [s]', row=11, col=1) - fig.update_yaxes(title_text='p [p.u.]', row=11, col=1) + p_cap = (v_sh_dq*np.conjugate(i_bus_dq)).real + q_cap = (v_sh_dq*np.conjugate(i_bus_dq)).imag - # v_vsc (calculated) - fig.add_trace(go.Scatter(x=tps, y=v_vsc_dq.real, mode='lines', line=dict(color='red', dash='solid')), - row=12, col=1) - fig.update_xaxes(title_text='Time [s]', row=12, col=1) - fig.update_yaxes(title_text='v_vsc_d [p.u.]', row=12, col=1) + p_load = v_dc*i_load - fig.add_trace(go.Scatter(x=tps, y=v_vsc_dq.imag, mode='lines', line=dict(color='red', dash='solid')), - row=12, col=2) - fig.update_xaxes(title_text='Time [s]', row=12, col=2) - fig.update_yaxes(title_text='v_vsc_q [p.u.]', row=12, col=2) - - e_cap = 0.5*self.c_dc*(v_dc**2) - e_ind = 0.5*self.l_dc*(i_L**2) - fig.add_trace(go.Scatter(x=tps, y=soc, name='battery soc', mode='lines', line=dict(color='red', dash='solid')), - row=13, col=1) - fig.add_trace(go.Scatter(x=tps, y=e_cap, name='cap energy', mode='lines', line=dict(color='blue', dash='dot')), - row=13, col=1) - fig.add_trace(go.Scatter(x=tps, y=e_ind, name='ind energy', mode='lines', line=dict(color='pink', dash='dot')), - row=13, col=1) - - fig.add_trace(go.Scatter(x=tps, y=np.ones_like(soc)*self.SOC_max_pu, name="soc lim", mode='lines', line=dict(color='green', dash='dot')), - row=13, col=1) - fig.update_xaxes(title_text='Time [s]', row=13, col=1) - fig.update_yaxes(title_text='energy [p.u.]', row=13, col=1) - - duty_cycle = self.kp_i_L*(self.kp_v_dc*(v_dc_ref - v_dcf) + x1 - i_Lf + self.Kff_idc*i_dcf + self.Kff_iload*i_loadf) + x2 - duty_cycle = np.clip(duty_cycle, 0.0, 1.0) - fig.add_trace(go.Scatter(x=tps, y=duty_cycle, name="duty cycle", mode='lines', line=dict(color='red', dash='solid')), - row=13, col=2) - fig.update_xaxes(title_text='Time [s]', row=13, col=2) - fig.update_yaxes(title_text='duty cycle [p.u.]', row=13, col=2) - - fig.add_trace(go.Scatter(x=tps, y=x3, mode='lines', line=dict(color='red', dash='solid')), - row=14, col=1) - fig.update_xaxes(title_text='Time [s]', row=14, col=1) - fig.update_yaxes(title_text='x3 [p.u.]', row=14, col=1) - - - name = f"{self.type_}_{self.id}" - fig.update_layout( title_text = name, - title_x=0.5, - showlegend = False, - ) - - fig.update_layout(height=1200*2, - width=800*2, - showlegend=False, - margin={'t': 0, 'l': 0, 'b': 0, 'r': 0}) - - fig.write_html(os.path.join(output_dir, name + ".html")) - - - \ No newline at end of file + results = DynamicalVariables( + name=['pi_cc_d', 'pi_cc_q', 'theta_pll', 'gamma_pll', 'i_vsc_d', 'i_vsc_q', 'v_sh_d', 'v_sh_q', 'i_bus_d', 'i_bus_q', 'int_vdc', 'v_dc', 'i_load', 'p_vsc', 'p_cap', 'pload', 'q_cap'], + component=f"{self.type_}_{self.id}", + value=[pi_cc_d, pi_cc_q, theta_pll, gamma_pll, i_vsc_d, i_vsc_q, v_sh_d, v_sh_q, i_bus_d, i_bus_q, int_vdc, v_dc, i_load, p_vsc, p_cap, p_load, q_cap], + time=tps + ) + return results \ No newline at end of file diff --git a/sting/system/core.py b/sting/system/core.py index aaddfa3..976f144 100644 --- a/sting/system/core.py +++ b/sting/system/core.py @@ -28,6 +28,7 @@ from sting.generator.gfmi_c import GFMIc from sting.generator.gfmi_d import GFMId from sting.generator.gfmi_e import GFMIe +from sting.generator.gfli_e import GFLIe from sting.reduced_order_model.linear_subsystem import LinearSubsystem from sting.line.pi_model import LinePiModel from sting.branch.series_rl import BranchSeriesRL @@ -59,6 +60,7 @@ class System: gfmi_d: list[GFMId] = None gfmi_e: list[GFMIe] = None gfli_a: list[GFLIa] = None + gfli_e: list[GFLIe] = None linear_subsystems: list[LinearSubsystem] = None buses: list[Bus] = None loads: list[Load] = None