From a52392f13f233841956692c904af1e6080dd5044 Mon Sep 17 00:00:00 2001 From: rkravis Date: Thu, 5 Mar 2026 14:16:55 -0800 Subject: [PATCH 1/2] add: GFMIe, t3 test case - needs debugging feat: GFMIe added to system --- .../small_signal_modeling/t3/inputs/buses.csv | 3 + .../t3/inputs/gfmi_e.csv | 2 + .../t3/inputs/infinite_sources.csv | 2 + .../small_signal_modeling/t3/inputs/lines.csv | 2 + .../small_signal_modeling/t3/inputs/loads.csv | 3 + .../t3/inputs/timepoints.csv | 2 + .../active_power_balance_by_bus.csv | 3 + .../t3/outputs/ac_power_flow/bus_voltage.csv | 3 + .../outputs/ac_power_flow/costs_summary.csv | 2 + .../ac_power_flow/generator_dispatch.csv | 3 + .../t3/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 | 21 + .../component_connection_matrices/G.csv | 21 + .../component_connection_matrices/H.csv | 11 + .../component_connection_matrices/L.csv | 11 + .../simulation_emt/branch_series_rl_0.html | 3888 +++++++++++++++++ .../t3/outputs/simulation_emt/gfmi_e_0.html | 3888 +++++++++++++++++ .../simulation_emt/infinite_sources_0.html | 3888 +++++++++++++++++ .../simulation_emt/shunt_parallel_rl_0.html | 3888 +++++++++++++++++ .../simulation_emt/shunt_parallel_rl_1.html | 3888 +++++++++++++++++ .../t3/outputs/small_signal_model/A.csv | 29 + .../t3/outputs/small_signal_model/B.csv | 29 + .../t3/outputs/small_signal_model/C.csv | 11 + .../t3/outputs/small_signal_model/D.csv | 11 + .../outputs/small_signal_model/gfmi_e_0.html | 3888 +++++++++++++++++ .../infinite_sources_0.html | 3888 +++++++++++++++++ .../outputs/small_signal_model/pa_rc_0.html | 3888 +++++++++++++++++ .../outputs/small_signal_model/pa_rc_1.html | 3888 +++++++++++++++++ .../outputs/small_signal_model/se_rl_0.html | 3888 +++++++++++++++++ .../t3/outputs/small_signal_model/u.csv | 9 + .../t3/outputs/small_signal_model/x.csv | 29 + .../t3/outputs/small_signal_model/y.csv | 11 + examples/small_signal_modeling/t3/run.py | 37 + sting/generator/gfmi_e.py | 787 ++++ 37 files changed, 39935 insertions(+) create mode 100644 examples/small_signal_modeling/t3/inputs/buses.csv create mode 100644 examples/small_signal_modeling/t3/inputs/gfmi_e.csv create mode 100644 examples/small_signal_modeling/t3/inputs/infinite_sources.csv create mode 100644 examples/small_signal_modeling/t3/inputs/lines.csv create mode 100644 examples/small_signal_modeling/t3/inputs/loads.csv create mode 100644 examples/small_signal_modeling/t3/inputs/timepoints.csv create mode 100644 examples/small_signal_modeling/t3/outputs/ac_power_flow/active_power_balance_by_bus.csv create mode 100644 examples/small_signal_modeling/t3/outputs/ac_power_flow/bus_voltage.csv create mode 100644 examples/small_signal_modeling/t3/outputs/ac_power_flow/costs_summary.csv create mode 100644 examples/small_signal_modeling/t3/outputs/ac_power_flow/generator_dispatch.csv create mode 100644 examples/small_signal_modeling/t3/outputs/ac_power_flow/line_flows.csv create mode 100644 examples/small_signal_modeling/t3/outputs/ac_power_flow/load_shedding.csv create mode 100644 examples/small_signal_modeling/t3/outputs/ac_power_flow/reactive_power_balance_by_bus.csv create mode 100644 examples/small_signal_modeling/t3/outputs/ac_power_flow/solver_status.csv create mode 100644 examples/small_signal_modeling/t3/outputs/component_connection_matrices/F.csv create mode 100644 examples/small_signal_modeling/t3/outputs/component_connection_matrices/G.csv create mode 100644 examples/small_signal_modeling/t3/outputs/component_connection_matrices/H.csv create mode 100644 examples/small_signal_modeling/t3/outputs/component_connection_matrices/L.csv create mode 100644 examples/small_signal_modeling/t3/outputs/simulation_emt/branch_series_rl_0.html create mode 100644 examples/small_signal_modeling/t3/outputs/simulation_emt/gfmi_e_0.html create mode 100644 examples/small_signal_modeling/t3/outputs/simulation_emt/infinite_sources_0.html create mode 100644 examples/small_signal_modeling/t3/outputs/simulation_emt/shunt_parallel_rl_0.html create mode 100644 examples/small_signal_modeling/t3/outputs/simulation_emt/shunt_parallel_rl_1.html create mode 100644 examples/small_signal_modeling/t3/outputs/small_signal_model/A.csv create mode 100644 examples/small_signal_modeling/t3/outputs/small_signal_model/B.csv create mode 100644 examples/small_signal_modeling/t3/outputs/small_signal_model/C.csv create mode 100644 examples/small_signal_modeling/t3/outputs/small_signal_model/D.csv create mode 100644 examples/small_signal_modeling/t3/outputs/small_signal_model/gfmi_e_0.html create mode 100644 examples/small_signal_modeling/t3/outputs/small_signal_model/infinite_sources_0.html create mode 100644 examples/small_signal_modeling/t3/outputs/small_signal_model/pa_rc_0.html create mode 100644 examples/small_signal_modeling/t3/outputs/small_signal_model/pa_rc_1.html create mode 100644 examples/small_signal_modeling/t3/outputs/small_signal_model/se_rl_0.html create mode 100644 examples/small_signal_modeling/t3/outputs/small_signal_model/u.csv create mode 100644 examples/small_signal_modeling/t3/outputs/small_signal_model/x.csv create mode 100644 examples/small_signal_modeling/t3/outputs/small_signal_model/y.csv create mode 100644 examples/small_signal_modeling/t3/run.py create mode 100644 sting/generator/gfmi_e.py diff --git a/examples/small_signal_modeling/t3/inputs/buses.csv b/examples/small_signal_modeling/t3/inputs/buses.csv new file mode 100644 index 0000000..ec202fb --- /dev/null +++ b/examples/small_signal_modeling/t3/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,1,1 +chile,1.00E+02,2.30E+02,60,0.95,1.3 \ No newline at end of file diff --git a/examples/small_signal_modeling/t3/inputs/gfmi_e.csv b/examples/small_signal_modeling/t3/inputs/gfmi_e.csv new file mode 100644 index 0000000..ad5a43c --- /dev/null +++ b/examples/small_signal_modeling/t3/inputs/gfmi_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,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,Tvdc_load,Pload +solar,chile,100,100,50,50,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,10,1,10,1,10,1,1000,1,1,0.01,0.01,0.01,1,1,0.01,0.01,0 \ No newline at end of file diff --git a/examples/small_signal_modeling/t3/inputs/infinite_sources.csv b/examples/small_signal_modeling/t3/inputs/infinite_sources.csv new file mode 100644 index 0000000..994d711 --- /dev/null +++ b/examples/small_signal_modeling/t3/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 diff --git a/examples/small_signal_modeling/t3/inputs/lines.csv b/examples/small_signal_modeling/t3/inputs/lines.csv new file mode 100644 index 0000000..8a683e5 --- /dev/null +++ b/examples/small_signal_modeling/t3/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,chile,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_modeling/t3/inputs/loads.csv b/examples/small_signal_modeling/t3/inputs/loads.csv new file mode 100644 index 0000000..79d806e --- /dev/null +++ b/examples/small_signal_modeling/t3/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_modeling/t3/inputs/timepoints.csv b/examples/small_signal_modeling/t3/inputs/timepoints.csv new file mode 100644 index 0000000..ad319a5 --- /dev/null +++ b/examples/small_signal_modeling/t3/inputs/timepoints.csv @@ -0,0 +1,2 @@ +name +timepoint_1 \ No newline at end of file diff --git a/examples/small_signal_modeling/t3/outputs/ac_power_flow/active_power_balance_by_bus.csv b/examples/small_signal_modeling/t3/outputs/ac_power_flow/active_power_balance_by_bus.csv new file mode 100644 index 0000000..6f6fc94 --- /dev/null +++ b/examples/small_signal_modeling/t3/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,5.000842627243224,-9.99090909090909e-9,0.0,5.000842617252305 +chile,timepoint_1,5.017184508118726,-9.99090909090909e-9,0.0,5.017184498127826 diff --git a/examples/small_signal_modeling/t3/outputs/ac_power_flow/bus_voltage.csv b/examples/small_signal_modeling/t3/outputs/ac_power_flow/bus_voltage.csv new file mode 100644 index 0000000..3418da9 --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/ac_power_flow/bus_voltage.csv @@ -0,0 +1,3 @@ +id,bus,timepoint,voltage_magnitude_pu,voltage_angle_deg +0,lima,timepoint_1,1.0,0.0 +1,chile,timepoint_1,1.0017997960714404,-0.0022997629674043206 diff --git a/examples/small_signal_modeling/t3/outputs/ac_power_flow/costs_summary.csv b/examples/small_signal_modeling/t3/outputs/ac_power_flow/costs_summary.csv new file mode 100644 index 0000000..a0e979f --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/ac_power_flow/costs_summary.csv @@ -0,0 +1,2 @@ +component,cost +total_cost_USD,-0.000039963636363636275 diff --git a/examples/small_signal_modeling/t3/outputs/ac_power_flow/generator_dispatch.csv b/examples/small_signal_modeling/t3/outputs/ac_power_flow/generator_dispatch.csv new file mode 100644 index 0000000..f57808e --- /dev/null +++ b/examples/small_signal_modeling/t3/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,5.000842627243224,-7.026642595242817 +0,gfmi_e,solar,timepoint_1,5.017184508118726,-6.33006174414215 diff --git a/examples/small_signal_modeling/t3/outputs/ac_power_flow/line_flows.csv b/examples/small_signal_modeling/t3/outputs/ac_power_flow/line_flows.csv new file mode 100644 index 0000000..5ce0d9d --- /dev/null +++ b/examples/small_signal_modeling/t3/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,chile,inf,5.000842617252306,-7.026642605233779,5.017184498127828,-6.330061754133121,10.018027115380134,-13.356704359366901 diff --git a/examples/small_signal_modeling/t3/outputs/ac_power_flow/load_shedding.csv b/examples/small_signal_modeling/t3/outputs/ac_power_flow/load_shedding.csv new file mode 100644 index 0000000..a2198f3 --- /dev/null +++ b/examples/small_signal_modeling/t3/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.99090909090909e-9,-9.990909090909043e-9 +chile,timepoint_1,-9.99090909090909e-9,-9.990909090909054e-9 diff --git a/examples/small_signal_modeling/t3/outputs/ac_power_flow/reactive_power_balance_by_bus.csv b/examples/small_signal_modeling/t3/outputs/ac_power_flow/reactive_power_balance_by_bus.csv new file mode 100644 index 0000000..b1dc563 --- /dev/null +++ b/examples/small_signal_modeling/t3/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,-7.026642595242817,-9.990909090909043e-9,0.0,-7.026642605233735 +chile,timepoint_1,-6.33006174414215,-9.990909090909054e-9,0.0,-6.330061754133077 diff --git a/examples/small_signal_modeling/t3/outputs/ac_power_flow/solver_status.csv b/examples/small_signal_modeling/t3/outputs/ac_power_flow/solver_status.csv new file mode 100644 index 0000000..b5cf3e1 --- /dev/null +++ b/examples/small_signal_modeling/t3/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.06941509246826172 diff --git a/examples/small_signal_modeling/t3/outputs/component_connection_matrices/F.csv b/examples/small_signal_modeling/t3/outputs/component_connection_matrices/F.csv new file mode 100644 index 0000000..22cfb01 --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/component_connection_matrices/F.csv @@ -0,0 +1,21 @@ +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')" +"('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 +"('gfmi_e_0', 'p_ref')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_e_0', 'q_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_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_dc_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_s')",0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_e_0', 'Pload')",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 diff --git a/examples/small_signal_modeling/t3/outputs/component_connection_matrices/G.csv b/examples/small_signal_modeling/t3/outputs/component_connection_matrices/G.csv new file mode 100644 index 0000000..a68a4a3 --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/component_connection_matrices/G.csv @@ -0,0 +1,21 @@ +Index,"('infinite_sources_0', 'v_ref_d')","('infinite_sources_0', 'v_ref_q')","('gfmi_e_0', 'p_ref')","('gfmi_e_0', 'q_ref')","('gfmi_e_0', 'v_ref')","('gfmi_e_0', 'v_dc_ref')","('gfmi_e_0', 'v_s')","('gfmi_e_0', 'Pload')" +"('infinite_sources_0', 'v_ref_d')",1.0,0.0,0.0,0.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,0.0,0.0,0.0 +"('infinite_sources_0', 'v_bus_D')",0.0,0.0,0.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,0.0,0.0,0.0 +"('gfmi_e_0', 'p_ref')",0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_e_0', 'q_ref')",0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0 +"('gfmi_e_0', 'v_ref')",0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0 +"('gfmi_e_0', 'v_dc_ref')",0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0 +"('gfmi_e_0', 'v_s')",0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0 +"('gfmi_e_0', 'Pload')",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 diff --git a/examples/small_signal_modeling/t3/outputs/component_connection_matrices/H.csv b/examples/small_signal_modeling/t3/outputs/component_connection_matrices/H.csv new file mode 100644 index 0000000..ba4ffa4 --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/component_connection_matrices/H.csv @@ -0,0 +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')" +"('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 diff --git a/examples/small_signal_modeling/t3/outputs/component_connection_matrices/L.csv b/examples/small_signal_modeling/t3/outputs/component_connection_matrices/L.csv new file mode 100644 index 0000000..2857f97 --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/component_connection_matrices/L.csv @@ -0,0 +1,11 @@ +Index,"('infinite_sources_0', 'v_ref_d')","('infinite_sources_0', 'v_ref_q')","('gfmi_e_0', 'p_ref')","('gfmi_e_0', 'q_ref')","('gfmi_e_0', 'v_ref')","('gfmi_e_0', 'v_dc_ref')","('gfmi_e_0', 'v_s')","('gfmi_e_0', 'Pload')" +"('infinite_sources_0', 'i_bus_D')",0.0,0.0,0.0,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,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 diff --git a/examples/small_signal_modeling/t3/outputs/simulation_emt/branch_series_rl_0.html b/examples/small_signal_modeling/t3/outputs/simulation_emt/branch_series_rl_0.html new file mode 100644 index 0000000..28058cc --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/simulation_emt/branch_series_rl_0.html @@ -0,0 +1,3888 @@ + + + +
+
+ + \ No newline at end of file diff --git a/examples/small_signal_modeling/t3/outputs/simulation_emt/gfmi_e_0.html b/examples/small_signal_modeling/t3/outputs/simulation_emt/gfmi_e_0.html new file mode 100644 index 0000000..1cae3af --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/simulation_emt/gfmi_e_0.html @@ -0,0 +1,3888 @@ + + + +
+
+ + \ No newline at end of file diff --git a/examples/small_signal_modeling/t3/outputs/simulation_emt/infinite_sources_0.html b/examples/small_signal_modeling/t3/outputs/simulation_emt/infinite_sources_0.html new file mode 100644 index 0000000..beb3c77 --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/simulation_emt/infinite_sources_0.html @@ -0,0 +1,3888 @@ + + + +
+
+ + \ No newline at end of file diff --git a/examples/small_signal_modeling/t3/outputs/simulation_emt/shunt_parallel_rl_0.html b/examples/small_signal_modeling/t3/outputs/simulation_emt/shunt_parallel_rl_0.html new file mode 100644 index 0000000..42b8dcd --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/simulation_emt/shunt_parallel_rl_0.html @@ -0,0 +1,3888 @@ + + + +
+
+ + \ No newline at end of file diff --git a/examples/small_signal_modeling/t3/outputs/simulation_emt/shunt_parallel_rl_1.html b/examples/small_signal_modeling/t3/outputs/simulation_emt/shunt_parallel_rl_1.html new file mode 100644 index 0000000..663b2ca --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/simulation_emt/shunt_parallel_rl_1.html @@ -0,0 +1,3888 @@ + + + +
+
+ + \ No newline at end of file diff --git a/examples/small_signal_modeling/t3/outputs/small_signal_model/A.csv b/examples/small_signal_modeling/t3/outputs/small_signal_model/A.csv new file mode 100644 index 0000000..2a8f7ef --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/small_signal_model/A.csv @@ -0,0 +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', 'v_dc_f_L')","('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,-753.7150506191037,-20.07077410038767,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,20.07077410038767,-753.7150506191037,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,985.0204944961328,-106.27041774209343,57.257103534748545,56.76605637169744,0.0,0.0,0.0,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,-106.27041774209343,-985.0204944961328,-56.76605637169744,57.257103534748545,0.0,0.0,0.0,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.0,0.0,0.0,0.0,0.0,0.0,-9.942305675058833,1.0726406032278109,0.0,0.0,0.0,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,18.471693229506368,0.0,0.0,3769.9111843077517,-75.39822368615502,376.99111843077515,0.0,0.0,-7518.072120528825,404.37598068511375,0.0,0.0,0.0,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,-396.9356977610736,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,225.11048256522963,21.400299080470646,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,-1871.523049881737,-224.63093765892924,0.0,0.0 +"('gfmi_e_0', 'i_bus_q')",0.0,0.0,1874.8823756421816,-21.585419499671545,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,224.63093765892924,-1871.523049881737,0.0,0.0 +"('gfmi_e_0', 'v_lcl_sh_d')",0.0,0.0,0.0,-40.063003640697495,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,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,-371.34397789733225,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,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.0,105.29046398050907,100.1178818484313,-1.1247817389117108e-15,0.0,0.0,-104.6829977562993,11.293882679818935,0.0,0.0,-100.0,0.0,0.0,0.0,0.0,-105.41458232567118,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,-10.0,0.0,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,-10.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,-376.99111843077515,376.99111843077515,376.99111843077515,376.99111843077515,376.99111843077515,0.0,-376.99111843077515,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.0,-0.3969356977610736,-0.37743552252960316,4.2403272574283795e-18,0.0,0.0,0.394645604048336,-0.042576934628909005,0.397403612898678,0.397403612898678,-0.397403612898678,-0.397403612898678,-0.397403612898678,-0.397403612898678,0.37699111843077515,0.397403612898678,-0.37699111843077515,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_e_0', 'v_dc_f_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,0.0,0.0,0.0,0.0,0.0,0.0,0.0,100.0,-100.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('pa_rc_0', 'v_bus_D')",5652.8628513789645,-150.5308050002535,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,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')",150.5308050002535,5652.8628513789645,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,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,-357.3020976289777,0.0,0.0,0.0,0.0,0.0,0.0,5614.5691215723655,-673.8928096073236,0.0,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,283.2197282782202,0.0,0.0,0.0,0.0,0.0,0.0,673.8928096073236,5614.5691215723655,0.0,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 diff --git a/examples/small_signal_modeling/t3/outputs/small_signal_model/B.csv b/examples/small_signal_modeling/t3/outputs/small_signal_model/B.csv new file mode 100644 index 0000000..ddcdb3d --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/small_signal_model/B.csv @@ -0,0 +1,29 @@ +Index,"('infinite_sources_0', 'v_ref_d')","('infinite_sources_0', 'v_ref_q')","('gfmi_e_0', 'p_ref')","('gfmi_e_0', 'q_ref')","('gfmi_e_0', 'v_ref')","('gfmi_e_0', 'v_dc_ref')","('gfmi_e_0', 'v_s')","('gfmi_e_0', 'Pload')" +"('infinite_sources_0', 'i_bus_d')",753.9822368615503,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +"('infinite_sources_0', 'i_bus_q')",0.0,753.9822368615503,0.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_e_0', 'angle_pc')",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,1.0,0.0,0.0,0.0,0.0,0.0 +"('gfmi_e_0', 'p_pc')",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,0.0,0.0,0.0 +"('gfmi_e_0', 'pi_vc')",0.0,0.0,0.0,0.0,10.0,0.0,0.0,0.0 +"('gfmi_e_0', 'i_vsc_d')",0.0,0.0,0.0,0.0,3769.9111843077517,0.0,0.0,0.0 +"('gfmi_e_0', 'i_vsc_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 +"('gfmi_e_0', 'v_lcl_sh_d')",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,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.0,105.29046398050907,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,10.0,0.0,0.0 +"('gfmi_e_0', 'x_2')",0.0,0.0,0.0,0.0,0.0,10.0,0.0,0.0 +"('gfmi_e_0', 'i_L')",0.0,0.0,0.0,0.0,0.0,376.99111843077515,376.99111843077515,0.0 +"('gfmi_e_0', 'v_dc')",0.0,0.0,0.0,0.0,-0.3969356977610736,-0.397403612898678,0.0,0.0 +"('gfmi_e_0', 'v_dc_f_L')",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 diff --git a/examples/small_signal_modeling/t3/outputs/small_signal_model/C.csv b/examples/small_signal_modeling/t3/outputs/small_signal_model/C.csv new file mode 100644 index 0000000..7669072 --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/small_signal_model/C.csv @@ -0,0 +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', 'v_dc_f_L')","('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.9996456332399041,-0.026619690914645725,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,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.026619690914645725,0.9996456332399041,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,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.06318488366565196,0.0,0.0,0.0,0.0,0.0,0.0,0.9928738149969942,-0.11917041366595324,0.0,0.0,0.0,0.0,0.0,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.05008424440222367,0.0,0.0,0.0,0.0,0.0,0.0,0.11917041366595324,0.9928738149969942,0.0,0.0,0.0,0.0,0.0,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 diff --git a/examples/small_signal_modeling/t3/outputs/small_signal_model/D.csv b/examples/small_signal_modeling/t3/outputs/small_signal_model/D.csv new file mode 100644 index 0000000..2857f97 --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/small_signal_model/D.csv @@ -0,0 +1,11 @@ +Index,"('infinite_sources_0', 'v_ref_d')","('infinite_sources_0', 'v_ref_q')","('gfmi_e_0', 'p_ref')","('gfmi_e_0', 'q_ref')","('gfmi_e_0', 'v_ref')","('gfmi_e_0', 'v_dc_ref')","('gfmi_e_0', 'v_s')","('gfmi_e_0', 'Pload')" +"('infinite_sources_0', 'i_bus_D')",0.0,0.0,0.0,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,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 diff --git a/examples/small_signal_modeling/t3/outputs/small_signal_model/gfmi_e_0.html b/examples/small_signal_modeling/t3/outputs/small_signal_model/gfmi_e_0.html new file mode 100644 index 0000000..a7f1e01 --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/small_signal_model/gfmi_e_0.html @@ -0,0 +1,3888 @@ + + + +
+
+ + \ No newline at end of file diff --git a/examples/small_signal_modeling/t3/outputs/small_signal_model/infinite_sources_0.html b/examples/small_signal_modeling/t3/outputs/small_signal_model/infinite_sources_0.html new file mode 100644 index 0000000..d491fb4 --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/small_signal_model/infinite_sources_0.html @@ -0,0 +1,3888 @@ + + + +
+
+ + \ No newline at end of file diff --git a/examples/small_signal_modeling/t3/outputs/small_signal_model/pa_rc_0.html b/examples/small_signal_modeling/t3/outputs/small_signal_model/pa_rc_0.html new file mode 100644 index 0000000..8bd9715 --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/small_signal_model/pa_rc_0.html @@ -0,0 +1,3888 @@ + + + +
+
+ + \ No newline at end of file diff --git a/examples/small_signal_modeling/t3/outputs/small_signal_model/pa_rc_1.html b/examples/small_signal_modeling/t3/outputs/small_signal_model/pa_rc_1.html new file mode 100644 index 0000000..f399d0b --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/small_signal_model/pa_rc_1.html @@ -0,0 +1,3888 @@ + + + +
+
+ + \ No newline at end of file diff --git a/examples/small_signal_modeling/t3/outputs/small_signal_model/se_rl_0.html b/examples/small_signal_modeling/t3/outputs/small_signal_model/se_rl_0.html new file mode 100644 index 0000000..c3f79d2 --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/small_signal_model/se_rl_0.html @@ -0,0 +1,3888 @@ + + + +
+
+ + \ No newline at end of file diff --git a/examples/small_signal_modeling/t3/outputs/small_signal_model/u.csv b/examples/small_signal_modeling/t3/outputs/small_signal_model/u.csv new file mode 100644 index 0000000..f0067fd --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/small_signal_model/u.csv @@ -0,0 +1,9 @@ +name,component,type,init +v_ref_d,infinite_sources_0,device,0.9657090864866837 +v_ref_q,infinite_sources_0,device,6.455596352286304e-18 +p_ref,gfmi_e_0,device,0.05036686791302277 +q_ref,gfmi_e_0,device,-0.06200046522918477 +v_ref,gfmi_e_0,device,0.990736481747031 +v_dc_ref,gfmi_e_0,device,1.0 +v_s,gfmi_e_0,device,1.0 +Pload,gfmi_e_0,device,0.0 diff --git a/examples/small_signal_modeling/t3/outputs/small_signal_model/x.csv b/examples/small_signal_modeling/t3/outputs/small_signal_model/x.csv new file mode 100644 index 0000000..35bc761 --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/small_signal_model/x.csv @@ -0,0 +1,29 @@ +name,component,type,init +i_bus_d,infinite_sources_0,"",0.05186117548896706 +i_bus_q,infinite_sources_0,"",0.0689103170162199 +angle_pc,gfmi_e_0,"",0.0 +w_pc,gfmi_e_0,"",1.0 +p_pc,gfmi_e_0,"",0.05036686791302277 +q_pc,gfmi_e_0,"",-0.06200046522918477 +pi_vc,gfmi_e_0,"",1.001178818484313 +i_vsc_d,gfmi_e_0,"",1.0529046398050907 +i_vsc_q,gfmi_e_0,"",0.04899768807921725 +i_bus_d,gfmi_e_0,"",0.05725710353474855 +i_bus_q,gfmi_e_0,"",0.05676605637169744 +v_lcl_sh_d,gfmi_e_0,"",0.9850204944961327 +v_lcl_sh_q,gfmi_e_0,"",-0.10627041774209343 +i_l_f,gfmi_e_0,"",1.0541458232567118 +v_dc_f,gfmi_e_0,"",1.0 +i_dc_f,gfmi_e_0,"",1.0541458232567118 +i_load_f,gfmi_e_0,"",0.0 +x_1,gfmi_e_0,"",0.0 +x_2,gfmi_e_0,"",0.0 +i_L,gfmi_e_0,"",1.0541458232567118 +v_dc,gfmi_e_0,"",1.0 +v_dc_f_L,gfmi_e_0,"",1.0 +v_bus_D,pa_rc_0,"",1.0 +v_bus_Q,pa_rc_0,"",0.0 +v_bus_D,pa_rc_1,"",1.0017997952644437 +v_bus_Q,pa_rc_1,"",-0.00004021067678490379 +i_br_D,se_rl_0,"",8.426172523048856e-6 +i_br_Q,se_rl_0,"",0.003599759052337936 diff --git a/examples/small_signal_modeling/t3/outputs/small_signal_model/y.csv b/examples/small_signal_modeling/t3/outputs/small_signal_model/y.csv new file mode 100644 index 0000000..1b821ae --- /dev/null +++ b/examples/small_signal_modeling/t3/outputs/small_signal_model/y.csv @@ -0,0 +1,11 @@ +name,component,type,init +i_bus_D,infinite_sources_0,"",0.05000842627243224 +i_bus_Q,infinite_sources_0,"",0.07026642595242817 +i_bus_D,gfmi_e_0,"",0.05008424440222367 +i_bus_Q,gfmi_e_0,"",0.06318488366565196 +v_bus_D,pa_rc_0,"",1.0 +v_bus_Q,pa_rc_0,"",0.0 +v_bus_D,pa_rc_1,"",1.0017997952644437 +v_bus_Q,pa_rc_1,"",-0.00004021067678490379 +i_br_D,se_rl_0,"",8.426172523048856e-6 +i_br_Q,se_rl_0,"",0.003599759052337936 diff --git a/examples/small_signal_modeling/t3/run.py b/examples/small_signal_modeling/t3/run.py new file mode 100644 index 0000000..9e51145 --- /dev/null +++ b/examples/small_signal_modeling/t3/run.py @@ -0,0 +1,37 @@ +# In progress - March 5, 2026 - Ruth + +# Import Python standard and third-party packages +from pathlib import Path + +# Import sting package +from sting import main +from sting.system.core import System + +# 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 step2(t): # no perturbation + return 0.0 + +# 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': step2}, + 'gfmi_e_0': {'p_ref': step2, + 'q_ref': step2, + 'v_ref': step2, + 'v_dc_ref': step2, + 'v_s': step2, + 'Pload': step2}} + +t_max = 1.0 + +_, 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('ok') \ No newline at end of file diff --git a/sting/generator/gfmi_e.py b/sting/generator/gfmi_e.py new file mode 100644 index 0000000..50e7503 --- /dev/null +++ b/sting/generator/gfmi_e.py @@ -0,0 +1,787 @@ +""" +(In progress - March 5, 2026 - Ruth) + +This module contains the GFMI generator that includes: +- Virtual inertia control +- Droop control for reactive power +- LCL filter +- Voltage magnitude controller +- DC-side DC-DC converter circuit and controller +- DC-side load with controller + +""" +# ---------------------- +# Import python packages +# ---------------------- +import numpy as np +from typing import NamedTuple, Optional, ClassVar +from dataclasses import dataclass, field +import plotly.graph_objects as go +from plotly.subplots import make_subplots +import os + +# ------------------ +# Import sting code +# ------------------ +from sting.utils.dynamical_systems import StateSpaceModel, DynamicalVariables +from sting.generator.core import Generator +from sting.utils.transformations import dq02abc, abc2dq0 + +# ----------- +# 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 + p_ref: float + q_ref: float + v_ref: float + angle_ref: float + v_vsc_d: float + v_vsc_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_dc: float # DC bus voltage + d: float # DC/DC converter duty cycle + i_dc: float # current into/out of inverter + i_L: float # DC/DC converter inductor current + x_1: float # DC voltage regulator integrator + x_2: float # DC current regulator integrator + i_load: float + v_dc_f_L: float + p_vsc: float + + +class VariablesEMT(NamedTuple): + x: DynamicalVariables + u: DynamicalVariables + y: DynamicalVariables + +# ----------- +# Main class +# ----------- +@dataclass(slots=True, kw_only=True, eq=False) +class GFMIe(Generator): + rf1_pu: float + xf1_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_x1_pu: float + txr_r2_pu: float + txr_x2_pu: float + h_s: float + kd_pu: float + droop_q_pu: float + tau_pc_s: float + kp_vc_pu: float + ki_vc_puHz: float + kp_v_dc: float # DC voltage regulator P gain + ki_v_dc: float # DC voltage regulator I gain [1/s] + kp_i_L: float # DC current regulator P gain + ki_i_L: float # DC current regulator I gain [1/s] + l_dc: float # DC/DC converter inductance, [pu] + c_dc: float # DC link capacitance, [pu] + v_dc_ref: float # DC bus reference voltage, [pu] + v_s: float # DC voltage source voltage, [pu] + Ti_L: float # measurement filter time constants [s] + Tv_dc: float + Ti_dc: float + Kff_idc: float + Kff_iload: float + Ti_load: float # for DC/DC controller - measurement filter + Tvdc_load: float # measurement that the load makes of the dc bus voltage + Pload: float + #bus_id: int = None + name: str = field(default_factory=str) + type: str = "gfmi_e" + #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): + return (self.txr_r1_pu + self.txr_r2_pu)*self.base_power_MVA/self.txr_power_MVA + + @property + def xf2_pu(self): + return (self.txr_x1_pu + self.txr_x2_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): + + # Power controller (Virtual inertia and droop control for reactive power) + tau_pc = self.tau_pc_s + wb = self.wbase + h = self.h_s + kd = self.kd_pu + droop_q = self.droop_q_pu + 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 + p_ref, q_ref = self.emt_init.p_ref, self.emt_init.q_ref + + pc_controller = StateSpaceModel( + A = np.array([ [0, wb, 0, 0], + [0, -kd/(2*h), -1/(2*h), 0], + [0, 0, -1/tau_pc, 0], + [0, 0, 0, -1/tau_pc]]), + B = np.vstack(( [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 1/(2*h), 0, 0], + 1/tau_pc*np.array([i_bus_d, i_bus_q, v_lcl_sh_d, v_lcl_sh_q, 0, 0, 0]), + 1/tau_pc*np.array([-i_bus_q, i_bus_d, v_lcl_sh_q, -v_lcl_sh_d, 0, 0, 0]))), + C = np.array([ [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 0, -droop_q]]), + D = np.vstack(( np.zeros((2,7)), + np.hstack((np.zeros((5, )), [droop_q, 1])))), + x = DynamicalVariables(name=['angle_pc', 'w_pc', 'p_pc', 'q_pc'], + init = [0.0, 1.0, p_ref, q_ref]), + u = DynamicalVariables(name=['v_lcl_sh_d', 'v_lcl_sh_q', 'i_bus_d', 'i_bus_q', 'p_ref', 'q_ref', 'v_ref']), + y = DynamicalVariables(name=['phi_pc', 'w_pc', 'v_lcl_sh_ref']) + ) + + # Voltage magnitude controller + kp_vc, ki_vc = self.kp_vc_pu, self.ki_vc_puHz + v_vsc_d = self.emt_init.v_vsc_d + + voltage_mag_controller = StateSpaceModel( + A = np.array([ [0] ]), + B = ki_vc*np.array([[1, -1]]), + C = np.array([[1], [0]]), + D = kp_vc*np.array([[1, -1], + [0, 0 ]]), + x = DynamicalVariables(name = ['pi_vc'], + init = [v_vsc_d]), + u = DynamicalVariables(name=['v_sh_mag_ref', 'v_sh_mag']), + y = DynamicalVariables(name=['v_vsc_d', 'v_vsc_q']) + ) + + + # LCL filter + 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 + 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/xf1 , 1 , 0 , 0 , -1/xf1 , 0], + [-1 , -rf1/xf1, 0 , 0 , 0 , -1/xf1], + [0 , 0 , -rf2/xf2 , 1 , 1/xf2 , 0], + [0 , 0 , -1 , -rf2/xf2, 0 , 1/xf2], + [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/xf1 , 0 , 0 , 0 , i_vsc_q], + [0 , 1/xf1 , 0 , 0 , -i_vsc_d], + [0 , 0 , -1/xf2 , 0 , i_bus_q], + [0 , 0 , 0 , -1/xf2 , -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"])) + + # DC side + + # Parameters + l_dc, c_dc, TiL, Tvdc, Tidc, Kp_vdc, Ki_vdc, Kp_iL, Ki_iL, Kff_idc, Kff_iload, Ti_load, Tvdc_load = 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.Tvdc_load + + # Initial conditions + v_dc, duty_cycle, i_dc, i_L, x1, x2, i_load, v_dc_f_L, Pload = self.emt_init.v_dc, self.emt_init.d, 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, self.emt_init.v_dc_f_L, self.Pload + + + # Controller + + dc_dc_controller = StateSpaceModel( + A = np.array([ + [-1/TiL, 0, 0, 0, 0, 0], + [0,-1/Tvdc, 0, 0, 0, 0], + [0, 0, -1/Tidc, 0, 0, 0], + [0, 0, 0, -1/Ti_load, 0, 0], + [0, -Ki_vdc, 0, 0, 0, 0], + [-Ki_iL, -Kp_vdc*Ki_iL, Kff_idc*Ki_iL, Kff_iload*Ki_iL, Ki_iL, 0]]), + B = np.array([ + [1/TiL, 0, 0, 0, 0], + [0, 1/Tvdc, 0, 0, 0], + [0, 0, 1/Tidc, 0, 0], + [0, 0, 0, 1/Ti_load, 0], + [0, 0, 0, 0, Ki_vdc], + [0, 0, 0, 0, Ki_iL*Kp_vdc]]), + + C = np.array([[-Kp_iL, -Kp_iL*Kp_vdc, Kp_iL*Kff_idc, Kp_iL*Kff_iload, Kp_iL, 1]]), + D = np.array([[0, 0, 0, 0, Kp_iL*Kp_vdc]]), + u = DynamicalVariables(name=['i_L', 'v_dc', 'i_dc', 'i_load', 'v_dc_ref']), + y = DynamicalVariables(name=['d']), + x = DynamicalVariables( + name = ['i_l_f', 'v_dc_f', 'i_dc_f', 'i_load_f','x_1', 'x_2'], + init = [i_L, v_dc, i_dc, i_load, x1, x2] + ) + ) + + # DC circuit + dc_circuit = StateSpaceModel( + A = wb*np.array([[0, (duty_cycle-1)/l_dc], + [(1-duty_cycle)/c_dc, 0]]), + B = wb*np.array([[1/l_dc, v_dc/l_dc, 0, 0], + [0, -i_L/c_dc, -1/c_dc, -1/c_dc]]), + C = np.eye(2), + D = np.zeros((2,4)), + u = DynamicalVariables(name=['v_s', 'd', 'i_dc','i_load']), + y = DynamicalVariables(name=['i_L','v_dc']), + x = DynamicalVariables( + name = ['i_L', 'v_dc'], + init = [i_L, v_dc] + ) + ) + + # Load control + load = StateSpaceModel( + A = np.array([[-1/Tvdc_load]]), + B = np.array([[1/Tvdc_load, 0]]), + C = np.array([[1/v_dc_f_L]]), + D = np.array([[0, -Pload/(v_dc_f_L**2)]]), + u = DynamicalVariables(name=['v_dc', 'Pload']), + y = DynamicalVariables(name=['i_load']), + x = DynamicalVariables( + name = ['v_dc_f_L'], + init = [v_dc_f_L] + ) + ) + + + # Construccion of CCM matrices + v_ref = self.emt_init.v_ref + angle_ref = self.emt_init.angle_ref + v_bus_D, v_bus_Q = self.emt_init.v_bus_D, self.emt_init.v_bus_Q + sinphi = np.sin(angle_ref*np.pi/180) + cosphi = np.cos(angle_ref*np.pi/180) + a = v_lcl_sh_d/v_ref + b = v_lcl_sh_q/v_ref + c = -sinphi*v_bus_D+cosphi*v_bus_Q + d = -cosphi*v_bus_D-sinphi*v_bus_Q + e = -sinphi*i_bus_d- cosphi*i_bus_q + f = cosphi*i_bus_d - sinphi*i_bus_q + + # DC circuit + a1 = v_vsc_d/v_dc + a2 = i_vsc_d/v_dc + a3 = self.emt_init.v_vsc_q/v_dc # is this just 0 ? + a4 = i_vsc_q/v_dc + a5 = -i_dc/v_dc + + # F is 25 x 15 matrix + Fccm = np.vstack(( np.hstack((np.zeros((2,9)), np.eye(2), np.zeros((2,4)))), # v_lcl_sh_dq + np.hstack((np.zeros((2,7)), np.eye(2), np.zeros((2,6)))), # i_bus_dq + np.zeros((3,15)), # p_ref, q_ref, v_ref + np.hstack( ( [0, 0, 1], np.zeros((12, )) )), # v_lcl_sh_ref + np.hstack( ( np.zeros((9, )), [a, b, 0, 0, 0, 0])), # v_lcl_sh_mag + np.hstack( ( np.zeros((2,3)), np.eye(2), np.zeros((2,10))) ), # v_vsc_dq + np.hstack( ( [c], np.zeros((14, )) )), # v_bus_d + np.hstack( ( [d], np.zeros((14, )) )), # v_bus_q + np.hstack( ( [0, 1], np.zeros((13, )))), # w + np.hstack( (np.zeros(12,), [1, 0, 0])), # i_L + np.hstack( (np.zeros(13,), [1, 0])), # v_dc + np.hstack( ([0, 0, 0, a2, a4, a1, a3, 0, 0, 0, 0, 0, 0, a5, 0])), # idc + np.hstack( (np.zeros(14,), [1])), # i_load + np.zeros((2,15)), # vdc_ref, v_s + np.hstack( (np.zeros(11,),[1, 0, 0, 0])), # d + np.hstack( ([0, 0, 0, a2, a4, a1, a3, 0, 0, 0, 0, 0, 0, a5, 0])), # i_dc + np.hstack( (np.zeros(14,), [1])), # i_load + np.hstack( (np.zeros(13,), [1, 0])), # v_dc + np.hstack( (np.zeros(13,), [1, 0])) # Pload + )) + # G is 25 x 8 matrix + Gccm = np.vstack(( np.zeros((4,8)) , + np.hstack( (np.eye(3), np.zeros((3,5)))), + np.zeros((4,8)), + np.hstack( (np.zeros((6,)), [cosphi, sinphi])), + np.hstack( (np.zeros((6,)), [-sinphi, cosphi])), + np.zeros(8, ), # w + np.zeros((4,8)), # i_L, v_dc, i_dc, i_load + np.hstack( ([0, 0, 0, 1], np.zeros(4,))), # vdc_ref + np.hstack( ([0, 0, 0, 0, 1], np.zeros(3,))), # v_s + np.zeros((4,8)), #d, i_dc, i_load, v_dc + np.hstack( (np.zeros(5,), [1, 0, 0])) # Pload + )) + + # H is 2 x 15 + Hccm = np.vstack(( np.hstack(( [e], np.zeros((6,)), [cosphi, -sinphi], np.zeros(6,) )), + np.hstack(( [f], np.zeros((6,)), [sinphi, cosphi], np.zeros(6,) )) + )) + + # L is 2 x 8 + Lccm = np.zeros((2,8)) + + components = [pc_controller, voltage_mag_controller, lcl_filter, dc_dc_controller, dc_circuit, load] + connections = [Fccm, Gccm, Hccm, Lccm] + + # Inputs and outputs + u = DynamicalVariables( + name=["p_ref", "q_ref", "v_ref", "v_dc_ref", "v_s", 'Pload', "v_bus_D", "v_bus_Q"], + type=["device", "device", "device", "device", "device", "device", "grid", "grid"], + init=[p_ref, q_ref, v_ref, self.v_dc_ref, self.v_s, self.Pload, 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): + 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) + + # 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.xf2_pu * 1j) * i_bus_DQ + + # Voltage and power references - at LCL filter capacitor + v_ref = abs(v_lcl_sh_DQ) + s_ref = v_lcl_sh_DQ * np.conjugate(i_bus_DQ) + p_ref = s_ref.real + q_ref = s_ref.imag + + # 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.xf1_pu * 1j) * i_vsc_DQ + + # Angle reference + angle_ref = np.angle(v_vsc_DQ, deg=True) + + # 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) + + # DC-side initial conditions + + v_dc = self.v_dc_ref + duty_cycle = (v_dc - self.v_s)/v_dc + p_vsc = (v_vsc_dq*np.conjugate(i_vsc_dq)).real # power at converter terminals + i_dc = p_vsc/v_dc + i_load = self.Pload/v_dc + i_L = (i_load+i_dc)/(1-duty_cycle) + x_1 = i_L - self.Kff_idc*i_dc - self.Kff_iload*i_load + x_2 = duty_cycle - self.kp_i_L*(x_1 - i_L + self.Kff_idc*i_dc + self.Kff_iload*i_load) + v_dc_f_L = v_dc + + # DC power balances: + # v_s*iL = (1-d)iL*v_dc + # v_s*iL + Pload = Pvsc + + self.emt_init = InitialConditionsEMT( + vmag_bus=vmag_bus, + vphase_bus=vphase_bus, + p_bus=p_bus, + q_bus=q_bus, + p_ref=p_ref, + q_ref=q_ref, + v_ref=v_ref, + angle_ref=angle_ref, + v_vsc_d=v_vsc_dq.real, + v_vsc_q = v_vsc_dq.imag, # added + 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, + d = duty_cycle, + i_dc = i_dc, + i_L = i_L, + x_1 = x_1, + x_2 = x_2, + i_load = i_load, + v_dc_f_L = v_dc_f_L, + p_vsc = p_vsc + ) + + + def define_variables_emt(self): + # States + # ------ + + # Initial conditions + angle_ref = self.emt_init.v_vsc_DQ_phase + p_ref, q_ref, v_ref = self.emt_init.p_ref, self.emt_init.q_ref, self.emt_init.v_ref + + # 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) + + v_vsc_d = self.emt_init.v_vsc_d + + v_dc, i_dc, i_L, x1, x2, i_load, v_dc_f_L = 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, self.emt_init.v_dc_f_L + + 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', 'v_dc_f_L'], + 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, v_dc_f_L] + ) + + # 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=["p_ref", "q_ref", "v_ref", "v_dc_ref", "v_s", 'Pload', "v_bus_a", "v_bus_b", "v_bus_c"], + component=f"{self.type_}_{self.id}", + type=["device", "device", "device", "device", "device", "device", "grid", "grid", "grid"], + init=[p_ref, q_ref, v_ref, self.v_dc_ref, self.v_s, self.Pload, v_bus_a, v_bus_b, v_bus_c] + ) + + # 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 + 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, v_dc_f_L = self.variables_emt.x.value + + # Get input values (external inputs) + p_ref, q_ref, v_ref, v_dc_ref, v_s, Pload, v_bus_a, v_bus_b, v_bus_c = self.variables_emt.u.value + + # convert relevant quantities to dq + 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 + + # Calculate DC-side current using current vsc voltage and current + # need to calculate v_vsc_dq, because it is an algebraic state so is not available in our state vector + i_vsc_d, i_vsc_q, _ = abc2dq0(i_vsc_a, i_vsc_b, i_vsc_c, angle_pc) + i_vsc_dq = i_vsc_d + 1j*i_vsc_q + v_sh_dq = v_sh_d + 1j*v_sh_q + v_vsc_dq = v_sh_dq + (self.rf1_pu + self.xf1_pu * 1j) * i_vsc_dq + + + # Do Q-V droop + v_sh_mag = (v_sh_d**2+v_sh_q**2)**0.5 # current voltage mag + v_sh_mag_ref = v_ref - self.droop_q_pu*(q_pc - q_ref) # droop on error from ref + + # NB updating algebraic states! + v_vsc_d = gamma + self.kp_vc_pu*(v_sh_mag_ref - v_sh_mag) # update + v_vsc_q = 0.0 # update + + # 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? + + # Load control - updating algebraic states! + i_load = Pload/v_dc_f_L + + i_dc = (v_vsc_d*i_vsc_d + v_vsc_q*i_vsc_q)/v_dc + + + # abc->dq conversions + + # Differential equations + # ---------------------- + + # Power controller: + def power_controller_dynamics(y, internal_inputs): + """ + The power controller has: virtual inertia, filter for active and reactive power. + """ + + # Definition of states for the ODEs of the power controller + angle_pc, w_pc, p_pc, q_pc = y[0], y[1], y[2], y[3] + + # Extract the list of parameters + tau_pc = self.tau_pc_s + wb = self.wbase + h = self.h_s + kd = self.kd_pu + + # Define inputs + v_sh_d, v_sh_q, i_bus_d, i_bus_q, p_ref = internal_inputs + + # Define ODEs that describe the dynamics of the power controller + d_angle_pc = wb * w_pc + d_w_pc = 1/(2*h) * (p_ref - p_pc - kd * (w_pc - 1)) + d_p_pc = 1/tau_pc * (- p_pc + v_sh_d * i_bus_d + v_sh_q * i_bus_q) + d_q_pc = 1/tau_pc * (- q_pc - v_sh_d * i_bus_q + v_sh_q * i_bus_d) + + return [d_angle_pc, d_w_pc, d_p_pc, d_q_pc] + + + def voltage_controller_dynamics(y, internal_inputs): + """ + The voltage controller has a PI structure that regulates the magnitude of the voltage at the + middle of the LCL filter. + """ + # Definition of states for the ODEs of the voltage controller + gamma = y[0] + + # Extract the list of parameters + kp_vc, ki_vc = self.kp_vc_pu, self.ki_vc_puHz + + v_sh_mag_ref, v_sh_d, v_sh_q = internal_inputs + + # Define ODEs that describe the dynamics of the voltage controller + d_gamma = ki_vc * v_sh_mag_ref - ki_vc * (v_sh_d**2 + v_sh_q**2)**0.5 + + return d_gamma + + + 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 + l1 = xf1/wb #todo check + l2 = xf2/wb + + # 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/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/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 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, v_dc_f_L = y[0], y[1], y[2], y[3], y[4], y[5], y[6], y[7], y[8] + + # Inputs + i_dc, i_load, v_dc_ref, v_s = internal_inputs + + # Parameters + l_dc, c_dc, TiL, Tvdc, Tidc, Kp_vdc, Ki_vdc, Kp_iL, Ki_iL, Kff_idc, Kff_iload, Ti_load, Tvdc_load = 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.Tvdc_load + wb = self.wbase + + # ODEs + + # DC-DC controller + d_i_Lf = (1/TiL)*(i_L - i_Lf) + d_v_dcf = (1/Tvdc)*(v_dc - v_dcf) + d_i_dcf = (1/Tidc)*(i_dc - i_dcf) + d_i_load_f = (1/Ti_load)*(i_load - i_loadf) + d_x_1 = Ki_vdc*(v_dc_ref - v_dcf) + 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 + + # 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) + + # Load control + d_v_dc_f_L = (1/Tvdc_load)*(v_dc - v_dc_f_L) + + 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_v_dc_f_L] + + + 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, v_dc_f_L], [i_dc, i_load, v_dc_ref, v_s]) + + return np.hstack([dy_pc, dy_vc, dy_lcl, dy_dc_side]) + + + 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, v_dc_f_L = 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, v_dc_f_L = self.variables_emt.x.value + + tps = self.variables_emt.x.time + p_ref, q_ref, v_ref, v_dc_ref, v_s, Pload, v_bus_a, v_bus_b, v_bus_c, = self.variables_emt.u.value + + # 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)]) + + fig = make_subplots( + rows=7, 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_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) + + 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")) + + + + From 8bade4b494051751b738ca9918d0464357788394 Mon Sep 17 00:00:00 2001 From: rkravis Date: Thu, 5 Mar 2026 14:21:47 -0800 Subject: [PATCH 2/2] see previous commit --- sting/generator/gfmi_e.py | 2 +- sting/system/core.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sting/generator/gfmi_e.py b/sting/generator/gfmi_e.py index 50e7503..6f86d93 100644 --- a/sting/generator/gfmi_e.py +++ b/sting/generator/gfmi_e.py @@ -1,5 +1,5 @@ """ -(In progress - March 5, 2026 - Ruth) +(In progress - March 5, 2026 - Ruth!!!) This module contains the GFMI generator that includes: - Virtual inertia control diff --git a/sting/system/core.py b/sting/system/core.py index 6f88671..97ac776 100644 --- a/sting/system/core.py +++ b/sting/system/core.py @@ -25,6 +25,7 @@ from sting.storage.core import Storage from sting.generator.infinite_source import InfiniteSource from sting.generator.gfmi_c import GFMIc +from sting.generator.gfmi_e import GFMIe from sting.reduced_order_model.linear_rom import LinearROM from sting.line.pi_model import LinePiModel from sting.branch.series_rl import BranchSeriesRL