├── LICENSE ├── README.md ├── _doc ├── 00_Deliverables_iTesla │ ├── D4.3_Annex_v.1.1.pdf │ └── D4.3_v.1.2.pdf ├── 01_Papers │ ├── 01_02_static_transient_Rafael_TransientStability_2014_Submitted.pdf │ ├── 03_PESGM_2014_afterreviews_v0.pdf │ └── 04_VoltageStability_Rafael_2014_Submitted.pdf ├── 02_Presentations │ ├── 00_iTeslaProject │ │ ├── 201304_itesla │ │ │ └── WP4p3 Review Brussels vFinal.pptx │ │ ├── 201306_itesla │ │ │ └── WP4p3_Nice.pptx │ │ ├── 201310_itesla │ │ │ └── WP4p3_Oslo_vFinal.pptx │ │ ├── 201401_itesla │ │ │ └── WP4p3_Brussels_v0.pptx │ │ ├── 201404_itesla │ │ │ ├── WP3_PSAT_vs_Eurostag.pptx │ │ │ └── WP4_RTE_Patris_v1.pptx │ │ └── 201406_itesla │ │ │ └── WP4_KTH_Stockholm_v0.pptx │ └── 01_Conferences │ │ ├── 2013_PES_GoldSession │ │ └── FRSS_PES_GM_Vancouver_vfinal.pptx │ │ └── 2014_PES_Poster │ │ ├── PESGM_Washington_2014_poster_printted.pdf │ │ └── PESGM_Washington_2014_poster_printted.pptx └── 03_Synthesis │ ├── v1_01_Static Overload Indexes.docx │ ├── v1_02_Static voltage Indexes.docx │ └── v1_05_b_Voltage Stability Indexes.docx ├── _pics ├── readmeimage.jpg └── readmeimage.pptx ├── _source ├── v0_1_iTesla │ ├── 1 Static_Overload │ │ ├── Over_Load.mat │ │ ├── horline.m │ │ ├── static_overload.m │ │ ├── static_overload_index_testing.m │ │ └── verline.m │ ├── 2 Static_UnderOver_Voltage │ │ ├── OverUnder_Voltage.mat │ │ ├── horline.m │ │ ├── static_voltage.m │ │ ├── static_voltage_index_testing.m │ │ └── verline.m │ ├── 3 Dynamic Transient │ │ ├── dynamic_transcient_index_testing.m │ │ ├── dynamic_transient.m │ │ └── transient.mat │ ├── 4 Dynamic Small_Signal │ │ ├── SmallSignal.mat │ │ ├── dynamic_smallsignal_testing.m │ │ ├── energy_sort.m │ │ ├── eraiTesla.m │ │ ├── fft_get.m │ │ ├── pronyiTesla.m │ │ └── smallsignal.m │ └── 5 Dynamic Voltage │ │ ├── EstimateE_and_X.m │ │ ├── Estimate_a_and_b.m │ │ ├── LOAD_ALL.mat │ │ ├── LONNY_ALL.mat │ │ ├── dynamic_voltagestability_testing.m │ │ ├── dynamic_voltagestbility_meanvalues.m │ │ └── voltagestability.m ├── v0_2_iTeslaUpdate │ ├── 1 Static_Overload │ │ ├── Over_Load.mat │ │ ├── static_overload.m │ │ └── static_overload_index_testing.m │ ├── 2 Static_UnderOver_Voltage │ │ ├── OverUnder_Voltage.mat │ │ ├── static_voltage.m │ │ └── static_voltage_index_testing.m │ ├── 3 Dynamic Transient │ │ ├── Gentrip_1.mat │ │ ├── Gentrip_2.mat │ │ ├── Gentrip_3.mat │ │ ├── Gentrip_4.mat │ │ ├── dynamic_transcient_index_testing.m │ │ ├── dynamic_transient.m │ │ └── transient.mat │ └── 4 Dynamic_SmallSignal_v1.2 │ │ ├── 7bus_fault.mat │ │ ├── Dynamic_smallsignal_example.m │ │ ├── KTH_Nordic32_fault.mat │ │ ├── Main_quinary_french_test.m │ │ ├── pronyiTesla.m │ │ ├── pronyiTesla.p │ │ ├── signal_filter.m │ │ └── sssi.m ├── v0_3_Nara │ ├── 01_Static_Overload │ │ ├── Over_Load.mat │ │ ├── Overload-1.mat │ │ ├── Overload-2.mat │ │ ├── Overload-3.mat │ │ ├── Static Overload Indexes.docx │ │ ├── static_overload.m │ │ └── static_overload_index_testing.m │ ├── 02_Static_UnderOver_Voltage │ │ ├── OverUnder_Voltage.mat │ │ ├── Static voltage Indexes.docx │ │ ├── static_voltage.m │ │ └── static_voltage_index_testing.m │ ├── 03_b_Voltage_Stability_Indexes_single_flow │ │ ├── 2bus-system.mat │ │ ├── Estimate.m │ │ ├── Estimate_a_b.m │ │ ├── KTH_Nordic_trip_L32.mat │ │ ├── KTH_Nordic_trip_L42.mat │ │ ├── Voltage_Stability_index_testing.m │ │ ├── dynamic_voltagestability_postcontingency.m │ │ ├── dynamic_voltagestability_precontingency.m │ │ ├── hline.m │ │ ├── indices_calculation.m │ │ ├── verline.m │ │ └── vline.m │ └── 2015_WP$_New Indices_Presentation.pptx └── v1 │ ├── 01_Static_Overload │ ├── MatlabImplementation │ │ ├── Over_Load.mat │ │ ├── Overload-1.mat │ │ ├── Overload-2.mat │ │ ├── Overload-3.mat │ │ ├── static_overload.m │ │ └── static_overload_index_testing.m │ └── PythonImplementation │ │ ├── Converted_data │ │ ├── S1.csv │ │ └── t.csv │ │ └── Python_code │ │ ├── .ipynb_checkpoints │ │ └── Static_Overload-checkpoint.ipynb │ │ ├── Static_Overload.ipynb │ │ └── requirements.txt │ ├── 02_Static_UnderOver_Voltage │ ├── OverUnder_Voltage.mat │ ├── static_voltage.m │ └── static_voltage_index_testing.m │ ├── 03_Dynamic Transient │ ├── Gentrip_1.mat │ ├── Gentrip_2.mat │ ├── Gentrip_3.mat │ ├── Gentrip_4.mat │ ├── dynamic_transcient_index_testing.m │ ├── dynamic_transient.m │ └── transient.mat │ ├── 04_a_ Dynamic Small_Signal_prony_ERA │ ├── SmallSignal.mat │ ├── dynamic_smallsignal_testing.m │ ├── energy_sort.m │ ├── eraiTesla.m │ ├── fft_get.m │ ├── pronyiTesla.m │ └── smallsignal.m │ ├── 04_b_Dynamic_SmallSignal_prony_only │ ├── 7bus_fault.mat │ ├── Dynamic_smallsignal_example.m │ ├── KTH_Nordic32_fault.mat │ ├── pronyiTesla.m │ ├── signal_filter.m │ └── sssi.m │ ├── 05_a_Dynamic Voltage │ ├── EstimateE_and_X.m │ ├── Estimate_a_and_b.m │ ├── LOAD_ALL.mat │ ├── LONNY_ALL.mat │ ├── dynamic_voltagestability_testing.m │ ├── dynamic_voltagestbility_meanvalues.m │ └── voltagestability.m │ └── 05_b_Voltage_Stability_Indexes │ ├── 2bus-system.mat │ ├── Estimate.m │ ├── Estimate_a_b.m │ ├── KTH_Nordic_trip_L32.mat │ ├── KTH_Nordic_trip_L42.mat │ ├── Voltage Stability Indexes.docx │ ├── Voltage_Stability_index_testing.m │ ├── dynamic_voltagestability_postcontingency.m │ ├── dynamic_voltagestability_precontingency.m │ ├── hline.m │ ├── indices_calculation.m │ ├── verline.m │ └── vline.m └── _thirdparty └── PronyCode_Source ├── 00119247.pdf └── prony_pnnl_sources_info.txt /README.md: -------------------------------------------------------------------------------- 1 | # TRISTAN: Time seRIes baSed sTability Assessment iNdexes 2 | Methods to assess power system (static and dynamic) stability margins from time-series data 3 | 4 | ![ScreenShot](https://github.com/ALSETLab/TRISTAN/blob/master/_pics/readmeimage.jpg) 5 | 6 | # Introduction and Motivation 7 | The main categories of computations performed for stability analysis purposes in power systems are contingency analysis, and security margin calculations. Contingency analysis methods consist determining system’s response to large disturbance, at a given operating point. Static and dynamic time-domain simulation methods are generally used in contingency analysis to assess the stability of a given power system. Static methods focus on the existence of equilibria and therefore rely on the solution of non-linear algebraic equations that assume equilibrium conditions of the system’s dynamics. Power flow based contingency analysis and continuation power flow (CPF) methods are some examples of static methods. Static methods are usually very efficient but they neither account for post contingency controls that depend on the system’s evolution nor capture more involved instability mechanisms. 8 | 9 | Time-domain methods, on the other hand, may have higher computational demands, but offer higher accuracy and better information (e.g. w.r.t the system’s response to a sequence of events). Such methods are attractive for Dynamic Security Assessment tools, specially those that do not have the facility to exploit the mathematical model's structure and can only use the resulting time-series from time-domain simulations. This is the case of the iPST platform (https://github.com/itesla/ipst) that relies in time-domain simulations for security assessment, and for which the the indexes provided in this repository were first developed. 10 | 11 | ## Related work 12 | A previoulsy released version of these indexes has been integrated into the iTesla platform, and are available in the open source distribution of the iPST. The available version of these indexes is in the iPST repository: [link](https://github.com/itesla/ipst/tree/e46b47547098915367f4fcfe96301d068b45b2ab/dynamic-indexes). 13 | 14 | ## Purpose of this repository 15 | Because the indexes are integrated into the platform's workflow, it is difficult to adapt them for other applications and time-series data sources (e.g. simulator outputs different than those in iPST or measurements). Hence, in an effort to provide these basic functionalities for use in other dynamic security assessment platforms or applications, all versions of the indexes developed along with testing data from simulations used in publications is provided in this repository. 16 | 17 | ## Repository Structure 18 | The repository is organized as follows: 19 | - ``./_docs/`` includes all the documentation available. The deliverables for the iTesla project for this work, papers written (for which results can be reproduced), presentations, and a synthesis of some of the indexes are provided in sub-folders. 20 | - ``./_pics/`` provides images with graphical results of the use of the indexes - for illustration purposes. 21 | - ``./_source/`` includes all development versions, and final set of indexes. Development versions are in folders market `v0_X...`, and the final version is in a folder named `v1`. 22 | - ``./_thirdparty`` includes the original code for a [Prony function developed by PNNL](https://github.com/ftuffner/DSIToolbox/blob/master/Ringdown130930/private/prgv2_5.m) which has been extensively modified to fit the purposes of the application. Please refer to this [link](https://github.com/ftuffner/DSIToolbox/) to obtain an updated or newer version of that code. 23 | 24 | ## Running the different indexes 25 | Each of the indeces are in an independent directories and are implemented in a Matlab function, that in some cases has dependencies to other functions. All functions are tested from individual Matlab scripts that call data and format the required inputs for excecution. All the indexes are located under ``./_sources/v1/``: 26 | - Static overload index: Run ``static_overload_index_testing.m`` on any of the three data sets ``Over_load-X.mat``. 27 | - Note: A Python implementation of this index is also available. 28 | - Static overvoltage index: Run ``static_voltage_index_testing.m`` on the data set ``OverUnder_Voltage.mat``. 29 | - Dynamic Transient index: Run ``dynamic_transcient_index_testing.m`` on the data sets ``transient.mat`` and ``Gentrip_X.mat``. 30 | - Small signal indexes: 31 | - Type A: under ``./_source/04_a_ Dynamic Small_Signal_prony_ERA/`` this method allows applying the ERA or Prony method, run ``dynamic_smallsignal_testing.m`` on data set ``SmallSignal.mat``. 32 | - Type B (Preferred): under ``./_source/04_b_Dynamic_SmallSignal_prony_only/``, a newer version applying only the Prony method that is more stable under unknown inputs, run ``Dynamic_smallsignal_example.m`` on data sets ``7bus_fault.mat`` and, ``KTHNordic32_fault.mat`` 33 | - Voltage stability indes: 34 | - Type A: under ``./_source/04_b_Dynamic_SmallSignal_prony_only/`` run ``dynamic_voltagestability_testing.m`` on ``LOAD_ALL.mat`` and ``LONNY_ALL.mat`` 35 | - Type B (Preferred): under ``./_source/05_b_Voltage_Stability_Indexes`` run ``Voltage_Stability_index_testing.m`` on data sets ``2bus-system.mat``, ``KTH_Nordic_trip_L32.mat`` and ``KTH_Nordic_trip_L42.mat``. 36 | 37 | # Cite our work! 38 | Please cite any of the following three papers depending on the use of our code: 39 | 40 | - Static and transient stability indeces: 41 | >> F. R. S. Sevilla and L. Vanfretti, "Static stability indexes for classification of power system time-domain simulations," 2015 IEEE Power & Energy Society Innovative Smart Grid Technologies Conference (ISGT), Washington, DC, 2015, pp. 1-5. [URL:]( http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=7131846&isnumber=7131775) 42 | 43 | - Small signal stability indices: 44 | >> F. R. S. Sevilla and L. Vanfretti, "A small-signal stability index for power system dynamic impact assessment using time-domain simulations," 2014 IEEE PES General Meeting | Conference & Exposition, National Harbor, MD, 2014, pp. 1-5. [URL]( http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=6938842&isnumber=6938773) 45 | 46 | - Voltage Stability Indices: 47 | - Type A: 48 | >> L. Vanfretti and F. R. S. Sevilla, "A three-layer severity index for power system voltage stability assessment using time-series from dynamic simulations," IEEE PES Innovative Smart Grid Technologies, Europe, Istanbul, 2014, pp. 1-5. [URL]( http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=7028788&isnumber=7028730). 49 | - Type B: 50 | >> V.S. Narasimham Arava and L. Vanfretti, "A Method to Estimate Power System Voltage Stability Margins using Time-series from Dynamic Simulations with Sequential Load Perturbations", paper submitted to the IEEE Transactions on Power Systems, 2017. Under Review. 51 | 52 | # Developers 53 | Felix Rafael Segundo Sevilla, Venkata Satya Narasimham Arava ([Narasimhamarava](https://github.com/Narasimhamarava)), Luigi Vanfretti ([lvanfretti](https://github.com/lvanfretti)). 54 | 55 | Wenting Li (liwenting0601@gmail.com) translated the static overload index to Python in Aug. 2017. 56 | 57 | # License 58 | Thi is free/libre software and the use is completely at your own risk; it can be redistributed and/or modified under the terms of the GNU Public License version 3. 59 | 60 | Copyright (C) 2017, Luigi Vanfretti. 61 | -------------------------------------------------------------------------------- /_doc/00_Deliverables_iTesla/D4.3_Annex_v.1.1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_doc/00_Deliverables_iTesla/D4.3_Annex_v.1.1.pdf -------------------------------------------------------------------------------- /_doc/00_Deliverables_iTesla/D4.3_v.1.2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_doc/00_Deliverables_iTesla/D4.3_v.1.2.pdf -------------------------------------------------------------------------------- /_doc/01_Papers/01_02_static_transient_Rafael_TransientStability_2014_Submitted.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_doc/01_Papers/01_02_static_transient_Rafael_TransientStability_2014_Submitted.pdf -------------------------------------------------------------------------------- /_doc/01_Papers/03_PESGM_2014_afterreviews_v0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_doc/01_Papers/03_PESGM_2014_afterreviews_v0.pdf -------------------------------------------------------------------------------- /_doc/01_Papers/04_VoltageStability_Rafael_2014_Submitted.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_doc/01_Papers/04_VoltageStability_Rafael_2014_Submitted.pdf -------------------------------------------------------------------------------- /_doc/02_Presentations/00_iTeslaProject/201304_itesla/WP4p3 Review Brussels vFinal.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_doc/02_Presentations/00_iTeslaProject/201304_itesla/WP4p3 Review Brussels vFinal.pptx -------------------------------------------------------------------------------- /_doc/02_Presentations/00_iTeslaProject/201306_itesla/WP4p3_Nice.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_doc/02_Presentations/00_iTeslaProject/201306_itesla/WP4p3_Nice.pptx -------------------------------------------------------------------------------- /_doc/02_Presentations/00_iTeslaProject/201310_itesla/WP4p3_Oslo_vFinal.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_doc/02_Presentations/00_iTeslaProject/201310_itesla/WP4p3_Oslo_vFinal.pptx -------------------------------------------------------------------------------- /_doc/02_Presentations/00_iTeslaProject/201401_itesla/WP4p3_Brussels_v0.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_doc/02_Presentations/00_iTeslaProject/201401_itesla/WP4p3_Brussels_v0.pptx -------------------------------------------------------------------------------- /_doc/02_Presentations/00_iTeslaProject/201404_itesla/WP3_PSAT_vs_Eurostag.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_doc/02_Presentations/00_iTeslaProject/201404_itesla/WP3_PSAT_vs_Eurostag.pptx -------------------------------------------------------------------------------- /_doc/02_Presentations/00_iTeslaProject/201404_itesla/WP4_RTE_Patris_v1.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_doc/02_Presentations/00_iTeslaProject/201404_itesla/WP4_RTE_Patris_v1.pptx -------------------------------------------------------------------------------- /_doc/02_Presentations/00_iTeslaProject/201406_itesla/WP4_KTH_Stockholm_v0.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_doc/02_Presentations/00_iTeslaProject/201406_itesla/WP4_KTH_Stockholm_v0.pptx -------------------------------------------------------------------------------- /_doc/02_Presentations/01_Conferences/2013_PES_GoldSession/FRSS_PES_GM_Vancouver_vfinal.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_doc/02_Presentations/01_Conferences/2013_PES_GoldSession/FRSS_PES_GM_Vancouver_vfinal.pptx -------------------------------------------------------------------------------- /_doc/02_Presentations/01_Conferences/2014_PES_Poster/PESGM_Washington_2014_poster_printted.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_doc/02_Presentations/01_Conferences/2014_PES_Poster/PESGM_Washington_2014_poster_printted.pdf -------------------------------------------------------------------------------- /_doc/02_Presentations/01_Conferences/2014_PES_Poster/PESGM_Washington_2014_poster_printted.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_doc/02_Presentations/01_Conferences/2014_PES_Poster/PESGM_Washington_2014_poster_printted.pptx -------------------------------------------------------------------------------- /_doc/03_Synthesis/v1_01_Static Overload Indexes.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_doc/03_Synthesis/v1_01_Static Overload Indexes.docx -------------------------------------------------------------------------------- /_doc/03_Synthesis/v1_02_Static voltage Indexes.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_doc/03_Synthesis/v1_02_Static voltage Indexes.docx -------------------------------------------------------------------------------- /_doc/03_Synthesis/v1_05_b_Voltage Stability Indexes.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_doc/03_Synthesis/v1_05_b_Voltage Stability Indexes.docx -------------------------------------------------------------------------------- /_pics/readmeimage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_pics/readmeimage.jpg -------------------------------------------------------------------------------- /_pics/readmeimage.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_pics/readmeimage.pptx -------------------------------------------------------------------------------- /_source/v0_1_iTesla/1 Static_Overload/Over_Load.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_1_iTesla/1 Static_Overload/Over_Load.mat -------------------------------------------------------------------------------- /_source/v0_1_iTesla/1 Static_Overload/horline.m: -------------------------------------------------------------------------------- 1 | function horline(t,v,lint) 2 | 3 | n=size(t,1); 4 | x=v*ones(n,1); 5 | 6 | 7 | hold on; plot(t,x,lint) 8 | -------------------------------------------------------------------------------- /_source/v0_1_iTesla/1 Static_Overload/static_overload.m: -------------------------------------------------------------------------------- 1 | 2 | function [Over_S,i2h,ridh]=static_overload(t,t1,S1,wf_i,p_1,dev0, flag1); 3 | %% Post-fault Over Load Index 4 | % This index is used to observer if the post-fault flows surpass the network capacity, 5 | % by monitoring the power flows through the transmission lines right after an outage occurs. 6 | % 7 | % 8 | % [Sindex,SingleIndex]=static_overload(t,t1,Signal,w,p,dev); 9 | % 10 | % t - Time vector 11 | % t1 - [tnom, tend, dt] 12 | % tnom - Initial time to be analized (sec) 13 | % tend - Final time to be analized (sec) 14 | % dt - Number of sampling times before the final time, to be analyzed 15 | % Signal - Signal to analyze, Apparent power flow 16 | % w - Weights for all buses, vector of ones for unitary weight 17 | % p - Exponent 18 | % dev - Deviation allowed of power flow from nominal value, i.e 10 for +10% 19 | % 20 | % Version 1.1 21 | 22 | dev0=dev0/100; 23 | %% Pre-processing the signals: Define the window of time to be analyzed 24 | 25 | % t1 =[tnom, tend, dt] with the following information: 26 | % 27 | % tnom -> Initial time to be analized (sec) 28 | % tend -> End time to be analized (sec) 29 | % dt -> Number of samplings to be analyzed, i.e. dt=3, t_analyzed = [t(tend-3),t(tend-2),t(tend-1),t(tend)] 30 | 31 | 32 | % The following section extracts from the time vector "t", 33 | % the approximated values of "tnom" and "tend" defined in t1 34 | 35 | tnom0 = find(t>=t1(1)*0.95 & t<=t1(1)*1.05 ); 36 | if size(tnom0,1)==0 37 | tnom0 = find(t>=t1(1)*0.9 & t<=t1(1)*1.1 ); 38 | end 39 | tend0 = find(t>=t1(2)*0.95 & t<=t1(2)*1.05); 40 | if size(tend0,1)==0 41 | tend0 = find(t>=t1(2)*0.9 & t<=t1(2)*1.1 ); 42 | end 43 | 44 | 45 | tnom = tnom0(1); 46 | tend = tend0(end); 47 | tdel = t(tnom:tend); 48 | dt = t1(3); 49 | 50 | 51 | 52 | %% OVERLOAD 53 | 54 | nl=size(S1,2); 55 | Snom = S1(tnom,:); % nominal value (pre-contingency) 56 | Smax = Snom*(1+dev0); % Over power flow limits 57 | Spost = S1(tend-dt:tend,:); 58 | zer = find(Smax<=0.001); 59 | 60 | if zer>1 61 | Smax(zer)=0.1; 62 | end 63 | 64 | 65 | Smean = mean(Spost); 66 | 67 | k=1; over_line=[]; 68 | for i=1:nl 69 | indxs_loc=(wf_i(i)*((abs(Smean(1,i))/abs(Smax(1,i)))^p_1)); 70 | index_red(i)=indxs_loc; 71 | 72 | 73 | if indxs_loc>=1 74 | indx(i)=indxs_loc; 75 | over_line(k)=i; % indices of lines violating limits 76 | k=k+1; 77 | else 78 | indx(i)=1; 79 | end 80 | 81 | 82 | rid(i,1) = index_red(i).^(1/p_1); 83 | if rid(i)<=1 84 | ridh(i,1)=1; 85 | i2h(i,1)=1; 86 | else 87 | ridh(i,1)= rid(i); 88 | i2h(i,1)=index_red(i); 89 | end 90 | 91 | end 92 | 93 | 94 | Over_S=sum(i2h)/nl; 95 | 96 | %% 97 | if flag1==1 98 | 99 | if Over_S>=1 100 | nvl=size(over_line,2); %Number of lines violating the limits 101 | Sextra_pu= indx(over_line)/max(indx(over_line)); 102 | for i=1:nvl 103 | if indx(over_line(i)).^(1/p_1)<=2 104 | indx_over_per(i,1)=((indx(over_line(i)).^(1/p_1))-1)*100; 105 | else 106 | indx_over_per(i,1)=((indx(over_line(i)).^(1/p_1)))*100; 107 | end 108 | end 109 | 110 | if nvl>=1 111 | 112 | figure;bar(Smean(1,over_line),'g');hold on;bar(Smax(1,over_line),'y'); legend('S_{mean}','S_{max_{limit}}') 113 | xlabel('Line Number');ylabel('MVA'); title(['Lines violating the limits=',num2str(nvl)]); 114 | set(gca,'XTick',[1:nvl]) 115 | set(gca,'XTickLabel',over_line) 116 | 117 | 118 | figure;bar(Sextra_pu,'r') 119 | rr=find(indx==max(indx)); 120 | title(['Line ',num2str(rr),' with maximum violation of ',num2str(max(indx_over_per)),'% more']) 121 | set(gca,'XTick',[1:nvl]) 122 | set(gca,'XTickLabel',over_line) 123 | 124 | 125 | %figure;plot(t,S1(:,rr));axis tight;title(['Line number ', num2str(rr),' with maximum violation']) 126 | figure;plot(tdel,S1(tnom:tend,rr));axis tight;title(['Line number ', num2str(rr),' with maximum violation']) 127 | hold on; plot(t(tend-dt:tend,1),S1(tend-dt:tend,rr),'linewidth',3) 128 | %hold on; hline(Smax(:,rr),'k--');hold on; hline(mean(Spost(:,rr)),'r') 129 | hold on; horline(tdel,Smax(:,rr),'k:');hold on; horline(tdel,mean(Spost(:,rr)),'r') 130 | xlabel('Time (sec)'); ylabel('MVA') 131 | end 132 | 133 | end 134 | 135 | end 136 | 137 | 138 | 139 | end -------------------------------------------------------------------------------- /_source/v0_1_iTesla/1 Static_Overload/static_overload_index_testing.m: -------------------------------------------------------------------------------- 1 | clear all;clc;close all 2 | 3 | %% Load time series 4 | 5 | load Over_Load 6 | 7 | %% POST-FAULT OVER LOADS 8 | 9 | t; % Time vector 10 | t1=[1,40,30]; % Section of Signal t1(1)= Initial Time 11 | % t1(2)= Final time 12 | % t1(3)= Number of samples prior t1(2) 13 | 14 | Signal = S1; % Input signal, Aparent power (S) size t x N 15 | nl = size(S1,2); % Determine the size of Signal 16 | wf_i = ones(1,nl); % Uniform weights in all Lines 17 | p = 3; % Exponent used to magnify problems, value between 1 to "inf" 18 | dev = 10; % Maximum Variation allowed from the nominal value (in %), i.e, 5 for 5% 19 | flag = 1; %PLotting results 20 | 21 | 22 | [f_x,f_scaled,f_noscaled]=static_overload(t,t1,Signal,wf_i,p,dev,flag); 23 | 24 | f_x 25 | 26 | % outputs 27 | % f_x = Final index 28 | % f_scaled = Indivial index of each Line with the exponent applyied 29 | % f_noscaled = Indivial index of each Line without exponent 30 | 31 | 32 | %% eof -------------------------------------------------------------------------------- /_source/v0_1_iTesla/1 Static_Overload/verline.m: -------------------------------------------------------------------------------- 1 | function verline(x,linetype,label); 2 | 3 | g=ishold(gca); 4 | hold on 5 | y=get(gca,'ylim'); 6 | h=plot([x x],y,linetype); 7 | 8 | if exist('label') 9 | xx=get(gca,'xlim'); 10 | xrange=xx(2)-xx(1); 11 | xunit=(x-xx(1))/xrange; 12 | if xunit<0.8 13 | text(x+0.01*xrange,y(1)+0.1*(y(2)-y(1)),label,'color',get(h,'color')) 14 | else 15 | text(x-.05*xrange,y(1)+0.1*(y(2)-y(1)),label,'color',get(h,'color')) 16 | end 17 | end -------------------------------------------------------------------------------- /_source/v0_1_iTesla/2 Static_UnderOver_Voltage/OverUnder_Voltage.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_1_iTesla/2 Static_UnderOver_Voltage/OverUnder_Voltage.mat -------------------------------------------------------------------------------- /_source/v0_1_iTesla/2 Static_UnderOver_Voltage/horline.m: -------------------------------------------------------------------------------- 1 | function horline(t,v,lint) 2 | 3 | n=size(t,1); 4 | x=v*ones(n,1); 5 | 6 | 7 | hold on; plot(t,x,lint) 8 | -------------------------------------------------------------------------------- /_source/v0_1_iTesla/2 Static_UnderOver_Voltage/static_voltage.m: -------------------------------------------------------------------------------- 1 | function [V_index,i2h,ridh]=static_voltage(t,t1,BVm,wv_i,p_2,dev,flag1,flag2); 2 | %% Post-fault Under/Over Voltage Index 3 | % Index for voltage of the transmission network right after an outage has occurred, 4 | % the index indicates if the voltage (BVm), surpass the minimum or 5 | % maximum limits of the operational standards 6 | % 7 | % 8 | % [Vindex,single_indexscaled,single_index]=satatic_voltage(t,t1,V,w,p,dev,Method); 9 | % 10 | % t - Time vector 11 | % t1 - [tnom, tend, dt] 12 | % tnom - Initial time to be analized (sec) 13 | % tend - Final time to be analized (sec) 14 | % dt - Number of sampling times before the final time, to be analyzed 15 | % V - Voltages vector 16 | % w - Weights for all buses, vector of ones for unitary weight 17 | % p - Exponent 18 | % dev - Deviation allowed of voltage from nominal value, i.e 2 for +-2% 19 | % Method - 0 to use the average value from analized window 20 | % 1 to take the largest value from analyzed window 21 | % 22 | % Version 1.0 23 | % 24 | dev=dev/100; 25 | 26 | %% Pre-processing the signals: Define the window of time to be analyzed 27 | 28 | % t1 =[tnom, tend, dt] with the following information: 29 | % 30 | % tnom -> Initial time to be analized (sec) 31 | % tend -> End time to be analized (sec) 32 | % dt -> Number of samplings to be analyzed, i.e. dt=3, t_analyzed = [t(tend-3),t(tend-2),t(tend-1),t(tend)] 33 | 34 | 35 | % The following section extracts from the time vector "t", 36 | % the approximated values of "tnom" and "tend" defined in t1 37 | 38 | tnom0 = find(t>=t1(1)*0.95 & t<=t1(1)*1.05 ); 39 | if size(tnom0,1)==0 40 | tnom0 = find(t>=t1(1)*0.9 & t<=t1(1)*1.1 ); 41 | end 42 | tend0 = find(t>=t1(2)*0.95 & t<=t1(2)*1.05); 43 | if size(tend0,1)==0 44 | tend0 = find(t>=t1(2)*0.9 & t<=t1(2)*1.1 ); 45 | end 46 | 47 | tnom = tnom0(1); 48 | tend = tend0(end); 49 | tdel = t(tnom:tend); 50 | dt = t1(3); 51 | 52 | %% Remove any buses that are out of service 53 | 54 | Vfault = []; 55 | Vfault = find(BVm(tend,:)==0); %Line out of service 56 | nbu=0; 57 | if size(Vfault,2)>0 58 | nbu=size(Vfault,2); 59 | BVm=BVm(:,[1:Vfault-1,Vfault+1:end]); 60 | % figure(101);plot(t,BVm);title(['Voltage magnitudes, without the faulty line ',num2str(Vfault)]) 61 | % title(['Voltage magnitudes, fault in line ',num2str(Vfault)]) 62 | end 63 | 64 | %% The following parameters are used to calculate the index: 65 | 66 | tpost = t(tend-dt:tend); % Period of time analyzed 67 | Vnom = BVm(tnom,:); % Nominal value (pre-contingency) 68 | Vpost = BVm(tend-dt:tend,:); % Voltage values post-contingency to be analyzed 69 | Vmin = Vnom*(1-dev); % Under voltage limits 70 | Vmax = Vnom*(1+dev); % Over voltage limits 71 | nb = size(Vnom,2); % Number of buses 72 | 73 | 74 | delV = (Vmax - Vmin)/2; %Equation 75 | Vmean = mean(Vpost); %Equation 76 | 77 | 78 | %% Calculation of the actual index 79 | 80 | for i=1:nb-nbu 81 | 82 | 83 | if flag1==1; 84 | 85 | % Index equaiton based on several points 86 | indxs =wv_i(1,i)*((abs(Vnom(i)-Vpost(:,i))./delV(i)).^p_2)'; 87 | else 88 | 89 | % Index equation base on average value 90 | indxs =wv_i(1,i)*((abs(Vnom(i)-Vmean(:,i))./delV(i)).^p_2)'; 91 | end 92 | 93 | 94 | 95 | % Applying considerations to understand the value of the index 96 | i2(i,1)=max(indxs); 97 | 98 | 99 | rid(i,1) = i2(i,1).^(1/p_2); 100 | 101 | if rid(i)<=1 102 | ridh(i,1)=1; 103 | i2h(i,1)=1; 104 | else if (rid(i)>=1) & (rid(i)<=5*(dev*100)) 105 | ridh(i,1)=rid(i); 106 | i2h(i,1)=i2(i); 107 | else 108 | ridh(i,1)= rid(i); 109 | i2h(i,1)=i2(i); 110 | end 111 | end 112 | 113 | 114 | end 115 | 116 | 117 | i2_tot=sum(i2); 118 | 119 | %%%%%%%%%%%% Under/Over Voltage Index %%%%%%%%% 120 | V_index = sum(i2h)/(nb-nbu); % The actual index normalized 121 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 122 | 123 | 124 | 125 | 126 | %% Ploting results 127 | r1=find(i2>=1); % index of lines violating limits 128 | nvl= size(r1,1); % number of lines violating limits 129 | 130 | r2=(i2).^(1/p_2); 131 | %nvlsevere=size(r20,1); % number of lines violating the limits more than "n" times the variation (delV) allowed. 132 | nvlsevere=0; 133 | 134 | 135 | 136 | if flag2 ==1 137 | 138 | if nvl>0 139 | figure;plot(t(tend-dt:tend,1),BVm(tend-dt:tend,r1));axis tight 140 | title(['Lines violating limits = ', num2str(nvl),' Index=',num2str(V_index)]) 141 | if nvlsevere>0 142 | %figure;plot(t,BVm(:,r20));axis tight 143 | figure;plot(tdel,BVm(tnom:tend,r20));axis tight 144 | title(['Lines (',num2str(nvlsevere), ') violating limits ',num2str(dev*100),' %']) 145 | end 146 | a= find(i2(r1)==max(i2(r1))); 147 | %a= a(1); 148 | mm=r1(1); 149 | %figure;plot(t,BVm(:,r1(a)));axis tight 150 | 151 | if flag1==1; 152 | 153 | figure;plot(tdel,BVm(tnom:tend,r1(mm)));axis tight 154 | hold on; plot(t(tend-dt:tend,1),BVm(tend-dt:tend,r1(mm)),'linewidth',3) 155 | %hold on; hline(Vmin(r1(mm)),'k--');hline(Vmax(r1(mm)),'k--') 156 | hold on; horline(tdel,Vmin(r1(mm)),'k:');horline(tdel,Vmax(r1(mm)),'k:') 157 | title(['Line with max violation ', num2str(r1(mm)),' from the ',num2str(nvl),' lines violating the limits (',num2str(dev*100),' %)']) 158 | 159 | else 160 | 161 | figure;plot(tdel,BVm(tnom:tend,mm));axis tight 162 | hold on; plot(t(tend-dt:tend,1),BVm(tend-dt:tend,mm),'linewidth',3) 163 | %hold on; hline(Vmin(mm),'k--');hline(Vmax(mm),'k--') 164 | %hold on; hline(mean(Vpost(:,mm)),'r') 165 | hold on; horline(tdel,Vmin(mm),'k:');horline(tdel,Vmax(mm),'k:') 166 | hold on; horline(tdel,mean(Vpost(:,mm)),'r') 167 | title(['Line ', num2str(mm),' with maximum violation, v=',num2str(V_index)]) 168 | xlabel('Time (sec)') 169 | ylabel('KV') 170 | 171 | end 172 | 173 | end 174 | 175 | end 176 | 177 | 178 | 179 | end 180 | 181 | 182 | -------------------------------------------------------------------------------- /_source/v0_1_iTesla/2 Static_UnderOver_Voltage/static_voltage_index_testing.m: -------------------------------------------------------------------------------- 1 | % POST-FAULT UNDER/OVER VOLTAGE 2 | % Sample script 3 | clear all;clc;close all 4 | 5 | %% Load time series 6 | load OverUnder_Voltage 7 | 8 | % POST-FAULT UNDER/OVER VOLTAGE 9 | %% Input data and options into the index 10 | t; % time vector 11 | 12 | t1 =[1,900,50]; % Select section of Signal t1(1)= Initial Time 13 | % t1(2)= Final time 14 | % t1(3)= Number of samples before time t1(2) 15 | % These make up the 16 | % window of data used to 17 | % compute the index. 18 | 19 | V = BVm; % Voltage mangitudes - Matrix of size t x N 20 | nb = size(BVm,2);% Determine the size of V 21 | wv_i = ones(1,nb); % Uniform weights in all Buses 22 | % If information about each bus is provided, then a 23 | % similar vector with the weights for each bus needs to 24 | % be provided by the user 25 | p = 3; % Exponent used to scale the index, value between 1 to "inf" 26 | Dev = 1; % Maximum voltage variation allowed (in %) of the nominal value, i.e. 2 for 2% 27 | Method = 0; % Select the method for time series analysis 28 | % Method=0 average value from analyzed time window (recomendend) 29 | % Method=1 largest value from analyzed time window 30 | flag =1; 31 | % Compute the index 32 | [v_x,v_scaled,v_noscaled] = static_voltage(t,t1,BVm,wv_i,p,Dev,Method,flag); 33 | % Display the index in the Command Window 34 | v_x 35 | 36 | % outputs 37 | % v_x = Final index 38 | % v_scaled = Indivial index of each bus with the exponent applyied 39 | % v_noscaled = Indivial index of each bus without exponent 40 | %% eof -------------------------------------------------------------------------------- /_source/v0_1_iTesla/2 Static_UnderOver_Voltage/verline.m: -------------------------------------------------------------------------------- 1 | function verline(x,linetype,label); 2 | 3 | g=ishold(gca); 4 | hold on 5 | y=get(gca,'ylim'); 6 | h=plot([x x],y,linetype); 7 | 8 | if exist('label') 9 | xx=get(gca,'xlim'); 10 | xrange=xx(2)-xx(1); 11 | xunit=(x-xx(1))/xrange; 12 | if xunit<0.8 13 | text(x+0.01*xrange,y(1)+0.1*(y(2)-y(1)),label,'color',get(h,'color')) 14 | else 15 | text(x-.05*xrange,y(1)+0.1*(y(2)-y(1)),label,'color',get(h,'color')) 16 | end 17 | end -------------------------------------------------------------------------------- /_source/v0_1_iTesla/3 Dynamic Transient/dynamic_transcient_index_testing.m: -------------------------------------------------------------------------------- 1 | clear all;clc;close all 2 | 3 | %% Load time series 4 | 5 | load Transient 6 | 7 | %% TRANSIENT STABILITY 8 | 9 | t; % Time vector size t x 1 10 | t1=[1,63]; % Section of Signal t1(1)= Initial Time in seconds 11 | % t1(2)= Final time in seconds 12 | 13 | delta; % Angle of the machines size t x N; 14 | M; % Two time interia (H) of the machines (M=2*H), size 1 x N 15 | 16 | [J]=dynamic_transient(t,t1,delta,M) 17 | 18 | 19 | % outputs 20 | % J = Final index 21 | 22 | 23 | -------------------------------------------------------------------------------- /_source/v0_1_iTesla/3 Dynamic Transient/dynamic_transient.m: -------------------------------------------------------------------------------- 1 | function [J]=dynamic_transient(t,t1,delta,M) 2 | %% Integral Square Generator Angle (ISGA) index. 3 | % Used to evaluate the transient stability of the system, simple approach that looks at the integral 4 | % of the square of the angular deviation from equilibrium (COI). 5 | % 6 | % [J]=dynamic_transient(t,t1,delta,M) 7 | % 8 | % t - Time vector 9 | % t1 - [tnom, tend, dt] 10 | % tnom - Initial time to be analized (sec) 11 | % tend - Final time to be analized (sec) 12 | % dt - Number of sampling times before the final time, to be analyzed 13 | % delta - Machine angles vector 14 | % M - Mechanical Starting time, two time interia (H) of the machines (M=2*H) 15 | % 16 | % Version 1.1 17 | % 18 | 19 | 20 | %% Pre-processing the signals: Define the window of time to be analyzed 21 | 22 | % t1 =[tnom, tend, dt] with the following information: 23 | % 24 | % tnom -> Initial time to be analized (sec) 25 | % tend -> End time to be analized (sec) 26 | % dt -> Number of samplings to be analyzed, i.e. dt=3, t_analyzed = [t(tend-3),t(tend-2),t(tend-1),t(tend)] 27 | 28 | 29 | % The following section extracts from the time vector "t", 30 | % the approximated values of "tnom" and "tend" defined in t1 31 | 32 | tnom0 = find(t>=t1(1)*0.95 & t<=t1(1)*1.05 ); 33 | if size(tnom0,1)==0 34 | tnom0 = find(t>=t1(1)*0.9 & t<=t1(1)*1.1 ); 35 | end 36 | tend0 = find(t>=t1(2)*0.95 & t<=t1(2)*1.05); 37 | if size(tend0,1)==0 38 | tend0 = find(t>=t1(2)*0.9 & t<=t1(2)*1.1 ); 39 | end 40 | 41 | 42 | tnom = tnom0(1); 43 | tend = tend0(end); 44 | tdel = t(tnom:tend); 45 | % dt = t1(3); 46 | 47 | if size(M,2)>1 48 | M=M'; 49 | end 50 | 51 | 52 | %% 53 | 54 | nm=size(delta,2); %machines number 55 | nt = size(tdel,1); % simulation length 56 | 57 | delnom = delta(tnom,:); 58 | del_uns = []; 59 | del_uns = find(delta(tend,:)<=-10000); %unstable machines 60 | 61 | 62 | if size(del_uns,2)>0 63 | nmu=size(del_uns,1); 64 | delta0=delta(:,[1:del_uns-1,del_uns+1:end]); 65 | M0=M([1:del_uns-1,del_uns+1:end],1); 66 | 67 | if flag1==1 68 | figure(401);plot(t,delta(:,del_uns));title(['Stop of generating unit ',num2str(del_uns)]) 69 | figure(400);plot(t,delta0);title(['Machines Angle of the working units (',num2str(nm-nmu),')']) 70 | end 71 | 72 | delta=delta0; 73 | M=M0; 74 | nm=nm-size(del_uns,2); 75 | 76 | end 77 | 78 | delta_a=delta([tnom:tend],:); 79 | 80 | 81 | for i=1:nm 82 | SM(:,i)=M(i)*delta_a(:,i); 83 | end 84 | 85 | num_coa = sum(SM,2); 86 | den_coa = sum(M); 87 | delta_coa = num_coa/den_coa; 88 | 89 | for i=1:nm 90 | Jg(:,i)=M(i)*(delta_a(:,i)-delta_coa).^2; 91 | %Jg(:,i)=(delta(:,i)-delta_coa).^2; 92 | Jcoa(:,i)=trapz(tdel,Jg(:,i)); 93 | end 94 | 95 | 96 | Mtot = sum(M); 97 | T = nt;%t(end); 98 | Jtot = sum(Jcoa); 99 | MT = 1/(Mtot*T); 100 | J1 = MT*Jtot; 101 | 102 | J=J1/nm; 103 | 104 | 105 | %keyboard 106 | -------------------------------------------------------------------------------- /_source/v0_1_iTesla/3 Dynamic Transient/transient.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_1_iTesla/3 Dynamic Transient/transient.mat -------------------------------------------------------------------------------- /_source/v0_1_iTesla/4 Dynamic Small_Signal/SmallSignal.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_1_iTesla/4 Dynamic Small_Signal/SmallSignal.mat -------------------------------------------------------------------------------- /_source/v0_1_iTesla/4 Dynamic Small_Signal/dynamic_smallsignal_testing.m: -------------------------------------------------------------------------------- 1 | clear all;clc;close all 2 | 3 | %% Load time series 4 | % 5 | load SmallSignal 6 | 7 | 8 | 9 | %% ERA & PRONY 10 | 11 | Method =2; % Method=1 (ERA analysis) 12 | % Method=2 (PRONY analysis recommended) 13 | 14 | t; % Time Vector 15 | SigAn = LP1; % Signals to analyze (Active power flows at critical lines) 16 | 17 | t1=[1,35,25]; % Select window section t1(1)= Initial Time 18 | % t1(2)= Final time 19 | % t1(3)= From where to start ERA 20 | Pcent=100; % Amount of signals to be considered, 100=100% for all signals, 21 | f=[0.1,1]; % Range of frequencies to analyze damping of modes f(1)=fmin, f(2)=fmax both in Hz 22 | Nmodes=[]; % Number of Modes to estimate on each approach, Nmodes=[]; automatic selection, Nmodes=[2]; force Algorithm to choose 2 modes. 23 | Damp=[0,5,10]; % Damping ratios, Calculate damping distance from each mode to the specified dampings, ie [0%, 5%, 10%] 24 | flag1=1; % if 1 show plots 25 | 26 | [GMI,AMI,SMI,Poles,Freq,Ener]=smallsignal(Method,t,SigAn,t1,Pcent,f,Nmodes,Damp,flag1); 27 | 28 | SMI 29 | AMI 30 | GMI 31 | 32 | %Outputs 33 | % 34 | % Ener Results of sorting signals "SigAn" according to energy 35 | % Ener.y Sorted signals from t1(1) to t1(2) 36 | % Ener.yh Sorted signals from t1(3) to t1(2) 37 | % Ener.t Time vector from t1(1) to t1(2) 38 | % Ener.th Time vector from t1(2) to t1(2) 39 | % 40 | % Freq Frequencies found from the FFT filter 41 | % 42 | % Poles Output of applying ERA or PRONY to set of signals "Ener.yh" 43 | % 44 | % if ERA 45 | % Poles.sys Estimated continous state-space model 46 | % 47 | % if PRONY 48 | % Poles.sys Estimated "A" matrix with modes identified 49 | % 50 | % SMI Single Mode Indicator, Matrix. 51 | % AMI All Mode Indicator, Vector. 52 | % GMI Global Mode Indicator, Gain. 53 | 54 | -------------------------------------------------------------------------------- /_source/v0_1_iTesla/4 Dynamic Small_Signal/energy_sort.m: -------------------------------------------------------------------------------- 1 | function [ymm,tss,ymm_sec,tsec]=energy_sort(t,t1,BVm,Pcent,flag1) 2 | % 3 | % [ymm,ymm_sec,tsec]=energy_sort(t,t1,Signals,Energy%,flag1) 4 | % 5 | % 6 | % 7 | % 8 | 9 | %% Pre-processing the signals: Define the window of time to be analyzed 10 | 11 | % t1 =[tnom, tend, dt] with the following information: 12 | % 13 | % tnom -> Initial time to be analized (sec) 14 | % tend -> End time to be analized (sec) 15 | % dt ->Time to start analyzing small-signal 16 | 17 | 18 | % The following section extracts from the time vector "t", 19 | % the approximated values of "tnom" and "tend" defined in t1 20 | 21 | tnom0 = find(t>=t1(1)*0.95 & t<=t1(1)*1.05 ); 22 | if size(tnom0,1)>=3 23 | tnom0 = find(t>=t1(1)*0.999 & t<=t1(1)*1.001 ); 24 | end 25 | if size(tnom0,1)==0 26 | tnom0 = find(t>=t1(1)*0.9 & t<=t1(1)*1.1 ); 27 | end 28 | 29 | tend0 = find(t>=t1(2)*0.95 & t<=t1(2)*1.05); 30 | if size(tend0,1)>=3 31 | tend0 = find(t>=t1(2)*0.999 & t<=t1(2)*1.001 ); 32 | end 33 | if size(tend0,1)==0 34 | tend0 = find(t>=t1(2)*0.9 & t<=t1(2)*1.1 ); 35 | end 36 | 37 | tnom = tnom0(1); 38 | tend = tend0(end); 39 | tdel = t(tnom:tend); 40 | %dt = t1(3); 41 | 42 | 43 | 44 | %% Selecting voltage magnitudes with largest oscillation content 45 | nb = size(BVm,2); 46 | tss = t(tnom:1:tend); % Time window to analyze 47 | tdss = [tnom:1:tend]; % 48 | y_invest = BVm(tdss,:); % Voltage magnitudes using selected interval 49 | 50 | 51 | tosc0 = find(tss>=t1(3)*0.95 & tss<=t1(3)*1.05); 52 | if size(tosc0,1)>=3 53 | tosc0 = find(tss>=t1(3)*0.999 & tss<=t1(3)*1.001 ); 54 | end 55 | if size(tosc0,1)==0 56 | tosc0 = find(tss>=t1(3)*0.9 & tss<=t1(3)*1.1 ); 57 | end 58 | dt=tosc0(end); 59 | 60 | % Calculating the Energy of the signals 61 | for i=1:nb 62 | yme(:,i)=y_invest(:,i)-mean(y_invest(:,i)); % Detrended signals 63 | %ydtr(:,i)=dtrend(y_invest(:,i)); % Detrended using matlab function 64 | En_sigs(i)=sqrt(sum(abs(yme(:,i).^2))); % Energy 65 | end 66 | 67 | 68 | [Ener,Ind] = sort(En_sigs','descend'); % Sort energy from largest to smallest 69 | 70 | Pcent=100-Pcent; 71 | Emax=max(Ener); 72 | Emin=(max(Ener)*Pcent)/100; 73 | 74 | kk=1; 75 | for i=1:nb 76 | if Ener(i)>= Emin 77 | EnerM(kk,1)=Ener(i); 78 | IndM(kk,1)=Ind(i); 79 | kk=kk+1; 80 | end 81 | end 82 | 83 | y_dtrend=yme(:,IndM); 84 | ymm=y_dtrend; 85 | % ymm_sec=ymm((end-dt:end),:); 86 | % tsec=tss(end-dt:end); 87 | %ymm_sec=ymm((dt:end),:); 88 | ymm_sec=dtrend(ymm((dt:end),:)); 89 | tsec=tss(dt:end); 90 | 91 | 92 | 93 | 94 | % y_dtrend=yme(:,Ind(1:end)); 95 | % ymm=y_dtrend; 96 | % ymm_sec=ymm((end-dt:end),:); 97 | % tsec=tss(end-dt:end); 98 | 99 | % keyboard 100 | 101 | %% 102 | 103 | if flag1==1 104 | %figure;plot(tss,BVm(tdss,Ind(1:end)));axis tight % Plot the most significant signals 105 | figure;plot(tss,ymm);axis tight % Plot the most significant signals detrended 106 | title(['Signals sorted according to Enery, more than ',num2str(Pcent),' %']) 107 | %figure;plot(tss(end-dt:end,1),ymm(end-dt:end,:));axis tight 108 | figure;plot(tss(dt:end,1),ymm_sec);axis tight 109 | title(['Selected Window to analyze: ',num2str(dt),' samplings before ', num2str(t(tend)),' sec']) 110 | end -------------------------------------------------------------------------------- /_source/v0_1_iTesla/4 Dynamic Small_Signal/fft_get.m: -------------------------------------------------------------------------------- 1 | function [fsend,magsend]=fft_get(t,x,alpha,flag1); 2 | 3 | t=t'; 4 | x=x'; 5 | 6 | n=size(t,2); % Number of points 7 | 8 | if mod(n,2) == 0 9 | n=n; 10 | else 11 | n=n-1; 12 | end 13 | 14 | 15 | 16 | %% Applying FFT to signal "x" and plotting real and imaginary part 17 | spectrum=fft(x); 18 | 19 | 20 | %keyboard 21 | 22 | %% 23 | %Verifying that first and middle components are real 24 | DCfisrst=spectrum(1:2); 25 | indNyq=n/2+1; 26 | NyquistMiddle=spectrum(indNyq-2:indNyq+2); 27 | 28 | 29 | %Fold the spectrum as algorithtm in Figure 12 of document 30 | spectrum = spectrum(1:indNyq); % truncate 31 | spectrum = spectrum/n; % scale 32 | spectrum(2:end) = 2*spectrum(2:end); % compensate for truncating negative freqs 33 | magnitude = abs(spectrum); % abs of complex numbers 34 | 35 | dt = t(3)-t(2); 36 | df = (1/dt)/n; % frequency resolution 37 | 38 | freqAx=[0:indNyq-1]'*df; % values of frequency axis 39 | 40 | [gains,indxs]=sort(magnitude','descend'); 41 | gains_norm=gains/gains(1); 42 | kk=find(gains_norm>=alpha); 43 | mm=size(kk,1); 44 | 45 | gsend=indxs(1:mm); 46 | fsend= freqAx(gsend); 47 | magsend=magnitude(gsend)'; 48 | 49 | %keyboard 50 | %% Various Plots 51 | mm=exist('flag1'); 52 | 53 | if mm 54 | 55 | 56 | % Plotting signal "x" and its first 20 points 57 | % figure 58 | % subplot(2,1,1) 59 | % plot(t,x);axis tight;grid on 60 | % ylabel('Units') 61 | % xlabel('Time[s]') 62 | % title('Signal') 63 | % subplot(2,1,2) 64 | % plot(t(1:20),x(1:20),'-o');axis tight;grid on 65 | % ylabel('Units') 66 | % xlabel('Time[s]') 67 | 68 | % figure 69 | % subplot(2,1,1) 70 | % plot(real(spectrum));axis tight;grid on 71 | % ylabel('Real') 72 | % title('Raw FFT spectrum') 73 | % subplot(2,1,2) 74 | % plot(imag(spectrum));axis tight;grid on 75 | % ylabel('Imaginary') 76 | % xlabel('Index number') 77 | 78 | figure 79 | plot(freqAx,magnitude);axis tight;grid on 80 | xlabel('Frequency[Hz]') 81 | ylabel('Magnitude[units]') 82 | [magMax,indMax]=max(magnitude); 83 | freqMax=freqAx(indMax); 84 | title(sprintf('Max magnitude=%f @ %fHz, \\Deltaf=%fHz',magMax,freqMax,df)) 85 | 86 | 87 | 88 | % figure 89 | % handlestem=stem(freqAx,magnitude); 90 | % set(handlestem(1),'Marker','none');grid on 91 | % xlabel('Frequency [Hz]') 92 | % ylabel('Magnitude [Hz]') 93 | % title(sprintf('Max magnitude=%f @ %fHz, \\Deltaf=%fHz',magMax,freqMax,df)) 94 | % 95 | % figure 96 | % fmax=find(freqAx==freqMax); 97 | % handlestem=stem(freqAx,magnitude); 98 | % axis([freqAx(fmax-5) freqAx(fmax+5) 0 max(magnitude)]) 99 | % set(handlestem(1),'Marker','none');grid on 100 | % xlabel('Frequency [Hz]') 101 | % ylabel('Magnitude [Hz]') 102 | % title(sprintf('Max magnitude=%f @ %fHz, \\Deltaf=%fHz',magMax,freqMax,df)) 103 | 104 | end -------------------------------------------------------------------------------- /_source/v0_1_iTesla/4 Dynamic Small_Signal/pronyiTesla.m: -------------------------------------------------------------------------------- 1 | function [lamda,model]=pronyiTesla(t,y,XX,tstart,tend,T,shift,tstplot,tedplot,plotFlag); 2 | %[model]=pronyanalysis(t,y,n,tstart,tend,T,shift,tstplot,tedplot,plotFlag); 3 | %Prony analysis program for fitting to a ringdown 4 | % Inputs: 5 | % t = time vector (does not need to be equally spaced) -- column vector 6 | % t(1) is assumed to be 0; if not, all time variables are shifted by t(1). 7 | % y = ringdown matrix of order N by NChan corresponding to t, each column is a different signal 8 | % n = order of the estimated model 9 | % tstart = row vector of order 1 by NChan. tstart(k) is the starting 10 | % time for analysis for y(:,k). 11 | % tend = ending times for analysis (same dimension as tstart) 12 | % shift = flag; if shift = 1, residues are shifted to t = 0. 13 | % If the data is noisy, reccomend shift = 0. 14 | % T = sample period for analysis 15 | % tsttplot = starting time for model simulation 16 | % tedplot = ending time for model simulation 17 | % plotFlag = if = 1, plot results 18 | % Outputs (structured array): 19 | % model.Poles = ringdown pole matrix -- column k is for column k of y 20 | % model.Res = ringdown residue matrix 21 | % model.K = ringdown offset row vector 22 | % model.yhat = model signal matrix 23 | % model.that = time vector for yhat (starts at tstart) 24 | % 25 | % NOTE: It is reccomended that the N/(1+NChan) < 200, where 26 | % N = total number of data points in y to be analyzed, and 27 | % NChan = number of columns in y. 28 | 29 | 30 | % 1.0 Setup 31 | 32 | %Basic error checks 33 | 34 | if (size(y,2)~=size(tstart,2))|(size(y,2)~=size(tend,2)); error('Dimension error in y, tstart, tend'); end; 35 | if (size(tstart,1)~=1)|(size(tend,1)~=1); error('Dimension error in tstart or tend'); end; 36 | if (T<=0)|(tstplot>=tedplot)|(max(t)min(tstart')); error('data error'); end; 37 | if (size(t,1) ~= size(y,1))|(size(t,2)~=1); error('Dimension error in y or t'); end; 38 | 39 | %Data parameters 40 | NChannels = size(y,2); 41 | 42 | %Shift time parameters 43 | tstart = tstart-t(1); 44 | tend = tend-t(1); 45 | tstplot = tstplot-t(1); 46 | tedplot = tedplot-t(1); 47 | t = t-t(1); 48 | 49 | %Set up analysis data and calculate offset 50 | tanalysis = T*[0:1:ceil(max(tend')/T)+1]'; 51 | Nstart = zeros(1,NChannels); 52 | Nend = zeros(1,NChannels); 53 | yanal = zeros(length(tanalysis),NChannels); 54 | K = zeros(1,NChannels); 55 | for k=1:NChannels 56 | Nstart(k) = floor(tstart(k)/T)+1; 57 | Nend(k) = ceil(tend(k)/T)+1; 58 | yanal(:,k) = spline(t,y(:,k),tanalysis); 59 | K(1,k) = mean(yanal(Nstart(k):Nend(k),k)); 60 | yanal(:,k) = yanal(:,k)-K(k); 61 | end 62 | clear k 63 | 64 | %Find model order 65 | NdataPoints = Nend-Nstart+1; %Number of data points used for analysis on each channel 66 | Ntotal = sum(NdataPoints'); %Total number of data points used for Prony analysis 67 | %nOrder = round(Ntotal/(1+NChannels))-10; %Order of Linear Prediction 68 | nOrder=XX; 69 | %if (nOrder>50); nOrder=50; end; %Limit order to avoid numerical problems 70 | 71 | % 2.0 Solve Linear Prediction 72 | 73 | %Build matrix and vector 74 | for k=1:NChannels 75 | Ym = zeros(NdataPoints(k)-nOrder,nOrder); 76 | for kk=1:nOrder 77 | Ym(:,kk) = yanal(Nstart(k)+nOrder-kk:Nstart(k)-kk+NdataPoints(k)-1,k); 78 | end 79 | yv = yanal(Nstart(k)+nOrder:Nstart(k)+NdataPoints(k)-1,k); 80 | if k==1; 81 | Ymatrix = Ym; 82 | yvector = yv; 83 | else 84 | Ymatrix = [Ymatrix;Ym]; %Cancatinate the channels 85 | yvector = [yvector;yv]; 86 | end 87 | end 88 | clear Ym yv k kk 89 | % acoef = pinv(Ymatrix)*yvector; %characteristic eqn. Pseudo inverse using SVD 90 | acoef = Ymatrix\yvector; %This provides a much more accurate solution than the above line 91 | 92 | %Find poles 93 | zPoles = roots([1;-acoef]); 94 | sPoles = log(zPoles)/T; 95 | 96 | 97 | 98 | % 3.0 Solve for residues 99 | Res = zeros(nOrder,NChannels); 100 | for k=1:NChannels 101 | ZMatrix = zeros(NdataPoints(k),nOrder); 102 | for kk=1:NdataPoints(k) 103 | ZMatrix(kk,:) = (zPoles.').^(kk-1); 104 | end 105 | Res(:,k) = ZMatrix\yanal(Nstart(k):Nend(k),k); 106 | if shift==1; 107 | Res(:,k) = Res(:,k).*(zPoles.^(-Nstart(k)+1)); %Shift residues to time 0 108 | end 109 | end 110 | clear k kk 111 | 112 | % 4.0 Re-order using energy 113 | P = zeros(nOrder,NChannels); 114 | R = zeros(size(Res)); 115 | for k=1:NChannels 116 | clear E 117 | for kk=1:nOrder 118 | if abs(real(sPoles(kk)))<1e-8 119 | E(kk)=Res(kk,k)^2*(tend(k)-tstart(k)); 120 | else 121 | E(kk)=(Res(kk,k)^2/(2*real(sPoles(kk))))*(exp(2*real(sPoles(kk))*(tend(k)-tstart(k)))-1); 122 | end 123 | end 124 | E=E(:); 125 | [x,ii]=sort(E); 126 | R(:,k)=Res(ii,k); 127 | P(:,k)=sPoles(ii); 128 | M=[length(ii):-1:1]'; 129 | R(:,k)=R(M,k); 130 | P(:,k)=P(M,k); 131 | end 132 | clear M k x ii E 133 | 134 | %Simulate; 135 | that = [tstplot:T:tedplot]'; 136 | yhat = zeros(length(that),NChannels); 137 | for k=1:NChannels 138 | yhat(:,k) = K(k).*ones(size(that)); 139 | for kk=1:length(that); 140 | for n=1:nOrder; 141 | yhat(kk,k) = yhat(kk,k) + R(n,k)*exp(P(n,k)*that(kk)); 142 | end 143 | end; 144 | end; 145 | yhat=real(yhat); 146 | 147 | % 5.0 Place output in structured array 148 | model.Poles = P; 149 | model.Res = R; 150 | model.K = K; 151 | model.that = that; 152 | model.yhat = yhat; 153 | 154 | lamda=sPoles; 155 | 156 | 157 | 158 | % 6.0 Plot results 159 | if plotFlag==1 160 | figure 161 | hold on 162 | h1 = plot(t,y); 163 | h2 = plot(that,yhat,'--*');axis tight 164 | hold off 165 | xlabel('Time (sec)') 166 | %legend('Actual','Prony') 167 | end 168 | 169 | %Original plots 170 | % if plotFlag==1 171 | % for k=1:size(yhat,2) 172 | % figure 173 | % n = find(t(t>=tstplot&t<=tedplot)); 174 | % hold on 175 | % h1 = plot(t(n),y(n,k),'k','linewidth',1.5); 176 | % h2 = plot(that,yhat(:,k),'r--','linewidth',1.5); 177 | % hold off 178 | % xlabel('Time (sec)') 179 | % legend('Actual','Prony') 180 | % end 181 | % end -------------------------------------------------------------------------------- /_source/v0_1_iTesla/4 Dynamic Small_Signal/smallsignal.m: -------------------------------------------------------------------------------- 1 | function [GMI_m,AMI_m,SMI,Poles,Frequencies,Ener]=smallsignal(flagMethod,t,SigAn,t1,Pcent,f,Nf,Damp,flag1); 2 | 3 | 4 | %% Sorting signals according to energy 5 | 6 | nsig = size(SigAn,2); % number of signals 7 | [ys,tss,ysec,tsec]=energy_sort(t,t1,SigAn,Pcent,flag1); 8 | 9 | nsec = size(ysec,2); % number of signals 10 | 11 | if nsec>=100 12 | y=ysec(:,1:100); 13 | else 14 | y=ysec; 15 | end 16 | 17 | Ener.y=ys; 18 | Ener.yh=ysec; 19 | Ener.t=tss; 20 | Ener.th=tsec; 21 | 22 | %keyboard 23 | 24 | %% Applying ideal filter (FFT) to signals with largest oscillation content 25 | 26 | nsig2 = size(y,2); %Number of signals 27 | fmin=f(1); %Minimum frequency Hz 28 | fmax=f(2); %Max requency Hz 29 | 30 | 31 | r=1; 32 | for i=1:nsig2 33 | [f_k,gain_k,]=fft_get(tsec,y(:,i),0.6); 34 | 35 | nfq = size(f_k,1); 36 | q = r+nfq-1; 37 | fqs(r:q,1) = f_k; 38 | fgains(r:q,1)=gain_k; 39 | fidx(i,1) = nfq; 40 | new = size(fqs,1); 41 | r = new+1; 42 | end 43 | 44 | Fred_find = fqs; 45 | nFreq=sum(fidx); 46 | clear fqs 47 | 48 | nsig; % Number of signals analyzed 49 | Fred_find; % Frequencies bwtween w1 and w2 within the set of signals 50 | fidx; % Number of frequencies found on each signal 51 | 52 | fss=unique(Fred_find); 53 | Frequencies = fss(find(fss~=0)); 54 | 55 | 56 | %% ERA 57 | if flagMethod==1 58 | 59 | if isempty(Nf) 60 | Nf=size(Frequencies,1); 61 | end 62 | 63 | 64 | 65 | nsig_y=size(y,2); 66 | fr = Nf; 67 | n=2*fr+2; %number of singular values to evaluate 68 | T = t(10)-t(9); 69 | [sysd,sv,mc] = eraiTesla(y,nsig_y,n,T,flag1); 70 | 71 | Poles.sys=sysd; 72 | Poles.sv=sv; 73 | Poles.mc=mc; 74 | 75 | nM = size(sysd.a,1); 76 | [Aq] = eig(sysd.a); 77 | fqmodes = Aq; 78 | ffreqq = abs(imag(fqmodes))/2/pi; 79 | fnfreqq = abs(fqmodes); 80 | fdampq = -cos(atan2(imag(fqmodes),real(fqmodes))); 81 | end 82 | 83 | %% Prony 84 | 85 | if flagMethod==2 86 | 87 | if isempty(Nf) 88 | Nf=size(Frequencies,1); 89 | end 90 | 91 | fr = Nf; % Number of modes 92 | t0 = tsec; % time vector of order 1xt 93 | yr = y; % ringdown matrix of order txNsig, each column is a different signal 94 | Nsig = size(yr,2); % number of signals or channels 95 | n=2*fr+2; %number of singular values to evaluate 96 | 97 | tstart = tsec(1)*ones(1,Nsig); %starting time for analysis 98 | tend = tsec(end)*ones(1,Nsig);%ending times for analysis 99 | T = tsec(end)-tsec(end-1); %sample period for analysis 100 | flag0 = 1; %if flag1 = 1, residues are shifted to t = 0. 101 | tstplot= tsec(1); %starting time for model simulation 102 | tedplot= tsec(end); %ending time for model simulation 103 | flagN = flag1; %if flag2=1, plot results 104 | 105 | [lamda,modelb]=pronyiTesla(t0,yr,n,tstart,tend,T,flag0,tstplot,tsec(end),flagN); 106 | 107 | Poles.sys=diag(lamda); 108 | 109 | nM = size(lamda,1); 110 | fqmodes = lamda; 111 | ffreqq = abs(imag(fqmodes))/2/pi; 112 | fnfreqq = abs(fqmodes); 113 | fdampq = -cos(atan2(imag(fqmodes),real(fqmodes))); 114 | end 115 | 116 | %% Small Signal Analysis 117 | 118 | [frso,idxef] = sort(ffreqq,'ascend'); 119 | 120 | 121 | fqmodes = fqmodes(idxef); 122 | ffreqq = ffreqq(idxef); 123 | fdampq = fdampq(idxef); 124 | 125 | 126 | if flagMethod==1 127 | fprintf(1,'\n All Estimated Modes using ERA '); 128 | end 129 | if flagMethod==2 130 | fprintf(1,'\n All Estimated Modes using PRONY '); 131 | end 132 | fprintf(1,'\n ------------------------------------------ '); 133 | header = sprintf('\n %15s %17s %10s ',... 134 | 'mode','freq(Hz)','damp (%)'); 135 | disp(header) 136 | for i=1:nM 137 | if imag(fqmodes(i))~=0 138 | % rr=mod(i,2); 139 | % if rr==1 140 | tstr = sprintf('%10.4f i%8.4f %10.4f %10.4f',... 141 | real(fqmodes(i)),imag(fqmodes(i)),ffreqq(i),fdampq(i)*100); 142 | % else 143 | % continue 144 | % end 145 | else 146 | tstr = sprintf('%10.4f ----- %10.4f %10.4f',... 147 | real(fqmodes(i)), ffreqq(i),fdampq(i)*100); 148 | end 149 | disp(tstr) 150 | end 151 | 152 | 153 | ww=find((ffreqq>=fmin) & (ffreqq<=fmax) ); 154 | 155 | nModes = size(ww,1); 156 | nMode = nModes/2; 157 | mods = fqmodes(ww); 158 | frqmode = ffreqq(ww); 159 | dampmode = fdampq(ww); 160 | 161 | 162 | fprintf(1,'\n Modes of interest within '); 163 | fprintf(1,'\n frequencies: %2.2f and %2.2f Hz ',fmin,fmax); 164 | fprintf(1,'\n ------------------------------------------ '); 165 | header = sprintf('\n %15s %17s %10s ',... 166 | 'mode','freq(Hz)','damp (%)'); 167 | disp(header) 168 | for i=1:nModes 169 | if imag(mods(i))~=0 170 | % rr=mod(i,2); 171 | % if rr==1 172 | tstr = sprintf('%10.4f i%8.4f %10.4f %10.4f',... 173 | real(mods(i)),imag(mods(i)),frqmode(i),dampmode(i)*100); 174 | % else 175 | % continue 176 | % end 177 | else 178 | tstr = sprintf('10.4f ----- %10.4f %10.4f',... 179 | real(mods(i)), frqmode(i),dampmode(i)*100); 180 | end 181 | disp(tstr) 182 | end 183 | 184 | dampmode=dampmode*100; 185 | 186 | keyboard 187 | 188 | th=acos(Damp/100); 189 | ths=pi-th; 190 | 191 | thl=acos(dampmode/100); 192 | thls=pi-thl; 193 | 194 | jj=1; kk=size(Damp,2); 195 | for i=1:1:nModes%i=1:2:nModes 196 | for m=1:1:kk 197 | SMI(jj,m)=thls(i)-ths(m); % Matrix, Single Mode Indicator(SMI) in rads 198 | end 199 | jj=jj+1; 200 | end 201 | 202 | 203 | 204 | SMIdeg=SMI*(180/pi); 205 | 206 | for m=1:kk 207 | AMI(1,m)=norm(SMI(:,m),2); %Vector, All Mode Indicator (AMI) in rads 208 | AMI_m(1,m)=min(SMI(:,m)); 209 | end 210 | 211 | 212 | 213 | 214 | AMIdeg = AMI*(180/pi); 215 | 216 | GMI = norm(AMI,2); % Gain, Global Mode Indicator (GMI) in rads 217 | GMI_m=min(AMI_m); 218 | 219 | 220 | 221 | 222 | -------------------------------------------------------------------------------- /_source/v0_1_iTesla/5 Dynamic Voltage/EstimateE_and_X.m: -------------------------------------------------------------------------------- 1 | function F = EstimateE_and_X(z) 2 | 3 | global P Q V 4 | 5 | % Unknown variables, 6 | % one delta variable for each operating point. 7 | n=size(P,1); 8 | delta = z(1:n); 9 | E = z(n+1); 10 | X = z(n+2); 11 | 12 | % Power Flow Equations 13 | F = [P*X - E*V.*sin(delta) 14 | Q*X - E*V.*cos(delta) + V.^2]; -------------------------------------------------------------------------------- /_source/v0_1_iTesla/5 Dynamic Voltage/Estimate_a_and_b.m: -------------------------------------------------------------------------------- 1 | function F = Estimate_a_and_b(z) 2 | global P Q 3 | 4 | % Unknown variables, 5 | % one delta variable for each operating point. 6 | 7 | a = z(1); 8 | b = z(2); 9 | 10 | % Power Flow Equations 11 | F = [a+b*P-Q]; -------------------------------------------------------------------------------- /_source/v0_1_iTesla/5 Dynamic Voltage/LOAD_ALL.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_1_iTesla/5 Dynamic Voltage/LOAD_ALL.mat -------------------------------------------------------------------------------- /_source/v0_1_iTesla/5 Dynamic Voltage/LONNY_ALL.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_1_iTesla/5 Dynamic Voltage/LONNY_ALL.mat -------------------------------------------------------------------------------- /_source/v0_1_iTesla/5 Dynamic Voltage/dynamic_voltagestbility_meanvalues.m: -------------------------------------------------------------------------------- 1 | function [Pmax,Vmax,P_pvcurve,V_pvcurve,states]=dynamic_voltagestbility_meanvalues(t,Nb,Nl,BVm,LP1,LQ1,Pmax0,x0,rn,flag1,clr1,clr2,lwid,fnum) 2 | %% Estimate Pmax and Vmax 3 | % 4 | % 5 | % [Ph,Vh,x]=dynamic_voltagestbility(t,Nb,Nl,V,P,Q,x0,r0,flag1,clr1,clr2,lwid) 6 | % t - Time vector 7 | % Nb - Bus number to be analyzed 8 | % Nl - Line number to be analyzed 9 | % V - Bus Voltages vector 10 | % P - Active power flows on lines 11 | % Q - Reactive pwoer flows on lines 12 | % x0 - inital guess to compute [d,E,X] 13 | % r0 - intial guess to compute [alpha,beta] 14 | % flag1 - 0 no plots 15 | % 1 shhow plots 16 | % clr1 - color for estimated PV data 17 | % clr2 - color for actual PV data 18 | % lwid - line width for actial data 19 | 20 | % 21 | %% 22 | 23 | 24 | [lsec,nsec]=size(BVm); 25 | 26 | jj=1;nn=lsec; 27 | for i=1:nsec 28 | V1(jj:nn,1)=BVm(:,i); 29 | Vk(i,1)=mean(BVm(:,i)); 30 | P1(jj:nn,1)=LP1(:,i); 31 | Pk(i,1)=mean(LP1(:,i)); 32 | Q1(jj:nn,1)=LQ1(:,i); 33 | Qk(i,1)=mean(LQ1(:,i)); 34 | t1(jj:nn,1)=t(:,i); 35 | tk(i,1)=mean(t(:,i)); 36 | ns=size(V1,1); 37 | jj=ns+1; 38 | nn=nn+lsec; 39 | end 40 | 41 | 42 | V = Vk; 43 | P = Pk; 44 | Q = Qk; 45 | 46 | 47 | %% 48 | global V P Q 49 | 50 | 51 | 52 | x01 = x0(1)*ones(size(P)); 53 | x02 = mean(V1); 54 | x0 = [x01; x02; x0(3)]; 55 | 56 | z0 = lsqnonlin(@EstimateE_and_X,x0); 57 | 58 | delta = z0(1:length(P)); 59 | E = z0(length(P)+1); 60 | X = z0(length(P)+2); 61 | 62 | 63 | r0 = lsqnonlin(@Estimate_a_and_b,rn); 64 | 65 | alpha = r0(1); 66 | beta = r0(2); 67 | 68 | states=[delta;E;X;alpha;beta]; 69 | 70 | 71 | %--- Calculating P-V curve ---% 72 | [Pmax,Pmaxindex]=max(abs(P)); 73 | Pdirection=sign(P(Pmaxindex)); 74 | Pmax=0; Pestim=[]; Vs=[]; Vu=[]; 75 | maxPflag=0; 76 | 77 | 78 | while maxPflag==0 79 | Qestim=alpha+beta*Pmax; 80 | Vs2=E^2/2-Qestim*X+sqrt(E^4/4-X^2*Pmax^2-Qestim*X*E^2); 81 | if imag(Vs2)==0 & real(Vs2)>=0 82 | Vs=[Vs sqrt(Vs2)]; 83 | Vu=[sqrt(E^2/2-Qestim*X-sqrt(E^4/4-X^2*Pmax^2-Qestim*X*E^2)) Vu]; 84 | Pestim=[Pestim Pmax]; 85 | Pmax=Pmax+.01*Pdirection; 86 | else 87 | maxPflag=1; 88 | end 89 | end 90 | 91 | [Pmax,Pmaxindex]=max(abs(Pestim)); 92 | 93 | %--- Save the Pmax and Vmax values ---% 94 | Pmax = Pestim(Pmaxindex); 95 | Vmax = Vs(Pmaxindex); 96 | 97 | 98 | %--- Save PV curve data for plots ---% 99 | V_pvcurve = [Vs Vu]; 100 | if Pdirection >= 0 101 | P_pvcurve = [Pestim sort(Pestim,2,'descend')]; 102 | else 103 | P_pvcurve = [Pestim sort(Pestim,2,'ascend')]; 104 | end 105 | 106 | 107 | %% 108 | mm=exist('clr1'); 109 | nn=exist('lwid'); 110 | kk=exist('fnum'); 111 | if flag1==1 112 | 113 | if mm 114 | figure;plot(P,V,clr2,'linewidth',lwid) 115 | hold on;plot(P_pvcurve,V_pvcurve,clr1); 116 | legend('actual','estimated') 117 | hold on; verline(Pmax,clr1) 118 | %hold on; hline(Vmax,clr1) 119 | hold on; verline(Pmax-(Pmax*Pmax0)/100,clr1) 120 | else 121 | 122 | 123 | figure;plot(P,V,'r','linewidth',3) 124 | hold on;plot(P_pvcurve,V_pvcurve,'b'); 125 | legend('actual','estimated') 126 | hold on; verline(Pmax,'b') 127 | %hold on; hline(Vmax,'b') 128 | hold on; verline(Pmax-(Pmax*Pmax0)/100,'b:') 129 | end 130 | 131 | if kk 132 | figure(fnum);hold on;plot(P,V,clr2,'linewidth',lwid) 133 | hold on;plot(P_pvcurve,V_pvcurve,clr1); 134 | legend('actual','estimated') 135 | hold on; verline(Pmax,clr1) 136 | %hold on; hline(Vmax,clr1) 137 | hold on; verline(Pmax-(Pmax*Pmax0)/100,clr1) 138 | end 139 | 140 | 141 | end -------------------------------------------------------------------------------- /_source/v0_2_iTeslaUpdate/1 Static_Overload/Over_Load.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_2_iTeslaUpdate/1 Static_Overload/Over_Load.mat -------------------------------------------------------------------------------- /_source/v0_2_iTeslaUpdate/1 Static_Overload/static_overload.m: -------------------------------------------------------------------------------- 1 | 2 | function [Over_S,i2h,ridh]=static_overload(t,S1,p_1,dev0); 3 | %% Post-fault Over Load Index 4 | % This index is used to observer if the post-fault flows surpass the network capacity, 5 | % by monitoring the power flows through the transmission lines right after an outage occurs. 6 | % 7 | % 8 | % [Sindex]=static_overload(t,t1,Signal,w,p,d); 9 | % 10 | % INPUTS 11 | % t - Time vector 12 | % S - Apparent power flow 13 | % p - Exponent 14 | % d - Deviation allowed of power flow from nominal value, e.g. 10 for +10% 15 | % 16 | % OUTPUTS 17 | % Sindex -Overload index 18 | % 19 | % Version 1.2 20 | 21 | 22 | %% OVERLOAD 23 | pre0 = 5; 24 | post0 = 100; 25 | 26 | dev0 = dev0/100; 27 | nl = size(S1,2); 28 | wf_i = ones(1,nl); % Uniform weights in all Lines is assumed 29 | Snom = mean(S1(1:pre0,:)); % Nominal value (pre-contingency) 30 | Smax = Snom*(1+dev0); % Over power flow limits 31 | Spost = S1(end-post0:end,:); 32 | Smean = mean(Spost); 33 | 34 | % Remove lines out of service 35 | xxx=[];k=1; 36 | for i=1:nl 37 | if abs(Smean(1,i))<1e-2 38 | xxx(k,1)=i; 39 | S1(:,i)=0; 40 | Smean(1,i)=0; 41 | Snom(1,i)=0; 42 | k=k+1; 43 | end 44 | end 45 | clear k 46 | 47 | 48 | k=1; over_line=[]; 49 | for i=1:nl 50 | indxs_loc=(wf_i(i)*((abs(Smean(1,i))/abs(Smax(1,i)))^p_1)); 51 | index_red(i)=indxs_loc; 52 | 53 | 54 | if indxs_loc>=1 55 | indx(i)=indxs_loc; 56 | over_line(k)=i; % indices of lines violating limits 57 | k=k+1; 58 | else 59 | indx(i)=1; 60 | end 61 | 62 | 63 | rid(i,1) = index_red(i).^(1/p_1); 64 | if rid(i)<=1 65 | ridh(i,1)=1; 66 | i2h(i,1)=1; 67 | else 68 | ridh(i,1)= rid(i); 69 | i2h(i,1)=index_red(i); 70 | end 71 | end 72 | 73 | over_line 74 | Over_S=sum(i2h)/nl; 75 | 76 | %% Plotting results (if required) 77 | % if Over_S>=1 78 | % nvl=size(over_line,2); %Number of lines violating the limits 79 | % Sextra_pu= indx(over_line)/max(indx(over_line)); 80 | % for i=1:nvl 81 | % if indx(over_line(i)).^(1/p_1)<=2 82 | % indx_over_per(i,1)=((indx(over_line(i)).^(1/p_1))-1)*100; 83 | % else 84 | % indx_over_per(i,1)=((indx(over_line(i)).^(1/p_1)))*100; 85 | % end 86 | % end 87 | % 88 | % if nvl>=1 89 | % 90 | % figure;bar(Smean(1,over_line),'g');hold on;bar(Smax(1,over_line),'y'); legend('S_{mean}','S_{max_{limit}}') 91 | % xlabel('Line Number');ylabel('MVA'); title(['Lines violating the limits=',num2str(nvl)]); 92 | % set(gca,'XTick',[1:nvl]) 93 | % set(gca,'XTickLabel',over_line) 94 | % 95 | % figure;bar(Sextra_pu,'r') 96 | % rr=find(indx==max(indx)); 97 | % title(['Line ',num2str(rr),' with maximum violation of ',num2str(max(indx_over_per)),'% more']) 98 | % set(gca,'XTick',[1:nvl]) 99 | % set(gca,'XTickLabel',over_line) 100 | % 101 | % figure;plot(t,S1(:,rr));axis tight;title(['Line number ', num2str(rr),' with maximum violation']) 102 | % hold on; plot(t(end-post0:end),S1(end-post0:end,rr),'linewidth',3) 103 | % hold on; horline(t,Smax(:,rr),'k:');hold on; horline(t,mean(Spost(:,rr)),'r') 104 | % xlabel('Time (sec)'); ylabel('MVA') 105 | % end 106 | % 107 | % end 108 | 109 | 110 | 111 | 112 | 113 | end -------------------------------------------------------------------------------- /_source/v0_2_iTeslaUpdate/1 Static_Overload/static_overload_index_testing.m: -------------------------------------------------------------------------------- 1 | clear all;clc;close all 2 | 3 | %% Load time series 4 | 5 | load Over_Load 6 | 7 | %% POST-FAULT OVER LOADS 8 | 9 | t; % Time vector 10 | S = S1; % Input signal, Aparent power (S) size t x N 11 | p = 3; % Exponent used to magnify problems, value between 1 to "inf" 12 | d = 10; % Maximum Variation allowed from the nominal value (in %), e.g, 10 for 10% 13 | 14 | 15 | f_x = static_overload(t,S,p,d); 16 | 17 | f_x 18 | 19 | % outputs 20 | % f_x = Final index 21 | 22 | 23 | %% eof -------------------------------------------------------------------------------- /_source/v0_2_iTeslaUpdate/2 Static_UnderOver_Voltage/OverUnder_Voltage.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_2_iTeslaUpdate/2 Static_UnderOver_Voltage/OverUnder_Voltage.mat -------------------------------------------------------------------------------- /_source/v0_2_iTeslaUpdate/2 Static_UnderOver_Voltage/static_voltage.m: -------------------------------------------------------------------------------- 1 | function [V_index,i2h,ridh]=static_voltage(t,BVm,p_2,dev); 2 | %% Post-fault Under/Over Voltage Index 3 | % Index for voltage of the transmission network right after an outage has occurred, 4 | % the index indicates if the voltage (V), surpass the limits of the operational standards 5 | % 6 | % 7 | % [Vindex]=satatic_voltage(t,V,p,d); 8 | % 9 | % INPUTS 10 | % t - Time vector 11 | % V - Voltages vector 12 | % p - Exponent 13 | % d - Deviation allowed of voltage from nominal value, e.g. 2 for +-2% 14 | % 15 | % OUTPUTS 16 | % Vindex -Under/Over voltage index 17 | % 18 | % 19 | % Version 1.1 20 | % 21 | 22 | dev=dev/100; 23 | 24 | 25 | %% The following parameters are used to calculate the index: 26 | pre0 = 5; 27 | post0 = 100; 28 | 29 | tpost = t(end-post0:end); % Period of time analyzed 30 | Vnom = mean(BVm(1:pre0,:)); % Nominal value (pre-contingency) 31 | Vpost = BVm(end-post0:end,:); % Voltage values post-contingency to be analyzed 32 | Vmin = Vnom*(1-dev); % Under voltage limits 33 | Vmax = Vnom*(1+dev); % Over voltage limits 34 | nb = size(Vnom,2); % Number of buses 35 | wv_i = ones(1,nb); % Uniform weights in all Buses 36 | 37 | 38 | delV = (Vmax - Vmin)/2; %Equation 39 | Vmean = mean(Vpost); %Equation 40 | 41 | 42 | % Remove bus out of service 43 | xxx=[];k=1; 44 | for i=1:nb 45 | if abs(Vmean(1,i))<1e-2 46 | xxx(k,1)=i; 47 | BVm(:,i)=0; 48 | Vmean(1,i)=0; 49 | Vnom(1,i)=0; 50 | Vmin(1,i)=0; 51 | Vmax(1,i)=0; 52 | wv_i(1,i)=0; 53 | k=k+1; 54 | end 55 | end 56 | clear k 57 | 58 | 59 | %% Calculation of the actual index 60 | 61 | for i=1:nb 62 | 63 | 64 | % Index equation base on average value 65 | indxs =wv_i(1,i)*((abs(Vnom(i)-Vmean(:,i))./delV(i)).^p_2)'; 66 | 67 | 68 | % Applying considerations to understand the value of the index 69 | i2(i,1)=max(indxs); 70 | 71 | 72 | rid(i,1) = i2(i,1).^(1/p_2); 73 | 74 | if rid(i)<=1 75 | ridh(i,1)=1; 76 | i2h(i,1)=1; 77 | else if (rid(i)>=1) & (rid(i)<=5*(dev*100)) 78 | ridh(i,1)=rid(i); 79 | i2h(i,1)=i2(i); 80 | else 81 | ridh(i,1)= rid(i); 82 | i2h(i,1)=i2(i); 83 | end 84 | end 85 | 86 | 87 | end 88 | 89 | 90 | i2_tot=sum(i2); 91 | 92 | %%%%%%%%%%%% Under/Over Voltage Index %%%%%%%%% 93 | V_index = sum(i2h)/(nb); % The actual index normalized 94 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 95 | 96 | 97 | 98 | %% Ploting results 99 | % r1 = find(i2>=1); % index of lines violating limits 100 | % nvl= size(r1,1); % number of lines violating limits 101 | % r2 = (i2).^(1/p_2); 102 | % nvlsevere=0; 103 | % 104 | % if nvl>0 105 | % figure;plot(t,BVm(:,r1));axis tight 106 | % title(['Lines violating limits = ', num2str(nvl),' Index=',num2str(V_index)]) 107 | % xlabel('Time (sec)') 108 | % ylabel('Voltage') 109 | % if nvlsevere>0 110 | % figure;plot(t,BVm(:,r20));axis tight 111 | % title(['Lines (',num2str(nvlsevere), ') violating limits ',num2str(dev*100),' %']) 112 | % xlabel('Time (sec)') 113 | % ylabel('Voltage') 114 | % end 115 | % a= find(i2(r1)==max(i2(r1))); 116 | % mm=r1(1); 117 | % 118 | % figure;plot(t,BVm(:,mm));axis tight 119 | % hold on; plot(t(end-post0:end),BVm(end-post0:end,mm),'linewidth',3) 120 | % hold on; horline(t,Vmin(mm),'k:');horline(t,Vmax(mm),'k:') 121 | % hold on; horline(t,mean(Vpost(:,mm)),'r') 122 | % title(['Line ', num2str(mm),' with maximum violation, v=',num2str(V_index)]) 123 | % xlabel('Time (sec)') 124 | % ylabel('Voltage') 125 | % end 126 | 127 | end 128 | 129 | 130 | -------------------------------------------------------------------------------- /_source/v0_2_iTeslaUpdate/2 Static_UnderOver_Voltage/static_voltage_index_testing.m: -------------------------------------------------------------------------------- 1 | % POST-FAULT UNDER/OVER VOLTAGE 2 | 3 | % Sample script 4 | clear all;clc;close all 5 | 6 | %% Load time series 7 | load OverUnder_Voltage 8 | 9 | % POST-FAULT UNDER/OVER VOLTAGE 10 | %% Input data and options into the index 11 | t; % time vector 12 | V = BVm; % Voltage mangitudes - Matrix of size t x N 13 | p = 3; % Exponent used to scale the index, value between 1 to "inf" 14 | d = 1; % Maximum voltage variation allowed (in %) of the nominal value, i.e. 2 for 2% 15 | 16 | % Compute the index 17 | [v_x] = static_voltage(t,V,p,d); 18 | 19 | % Display the index in the Command Window 20 | v_x 21 | 22 | % outputs 23 | % v_x = Final index 24 | %% eof -------------------------------------------------------------------------------- /_source/v0_2_iTeslaUpdate/3 Dynamic Transient/Gentrip_1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_2_iTeslaUpdate/3 Dynamic Transient/Gentrip_1.mat -------------------------------------------------------------------------------- /_source/v0_2_iTeslaUpdate/3 Dynamic Transient/Gentrip_2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_2_iTeslaUpdate/3 Dynamic Transient/Gentrip_2.mat -------------------------------------------------------------------------------- /_source/v0_2_iTeslaUpdate/3 Dynamic Transient/Gentrip_3.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_2_iTeslaUpdate/3 Dynamic Transient/Gentrip_3.mat -------------------------------------------------------------------------------- /_source/v0_2_iTeslaUpdate/3 Dynamic Transient/Gentrip_4.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_2_iTeslaUpdate/3 Dynamic Transient/Gentrip_4.mat -------------------------------------------------------------------------------- /_source/v0_2_iTeslaUpdate/3 Dynamic Transient/dynamic_transcient_index_testing.m: -------------------------------------------------------------------------------- 1 | clear all;clc;close all 2 | 3 | %% Load time series 4 | 5 | load Transient 6 | 7 | %% TRANSIENT STABILITY 8 | 9 | t; % Time vector size t x 1 10 | delta; % Angle of the machines size t x N; 11 | M; % Two time interia (H) of the machines (M=2*H), size 1 x N 12 | 13 | [J]=dynamic_transient(t,delta,M) 14 | 15 | 16 | % outputs 17 | % J = Final index 18 | 19 | 20 | -------------------------------------------------------------------------------- /_source/v0_2_iTeslaUpdate/3 Dynamic Transient/dynamic_transient.m: -------------------------------------------------------------------------------- 1 | function [J,delta_N,xxx]=dynamic_transient(t,delta,M) 2 | %% Integral Square Generator Angle (ISGA) index. 3 | % Used to evaluate the transient stability of the system, simple approach that looks at the integral 4 | % of the square of the angular deviation from equilibrium (COI). 5 | % 6 | % J =dynamic_transient(t,delta,M) 7 | % 8 | % INPUTS 9 | % t - Time vector 10 | % delta - Machine angles vector 11 | % M - Mechanical Starting time, two time interia (H) of the machines (M=2*H) 12 | % 13 | % OUTPUTS 14 | % J - Transien stability index 15 | % 16 | % Version 1.2 17 | % 18 | 19 | 20 | if size(M,2)>1 21 | M=M'; 22 | end 23 | 24 | 25 | %% 26 | nm=size(delta,2); % machines number 27 | nt = size(t,1); % simulation length 28 | 29 | post0 = 100; 30 | delta_post = delta(end-post0:end,:); 31 | delta_mean = mean(delta_post); 32 | 33 | % Remove generators out of service 34 | xxx=[];k=1; 35 | for i=1:nm 36 | if delta_mean(1,i)<-1e20 37 | xxx(k,1)=i; 38 | delta(:,i)=0; 39 | delta_mean(1,i)=0; 40 | M(i)=0; 41 | k=k+1; 42 | end 43 | end 44 | clear k 45 | delta_N=delta; 46 | 47 | 48 | 49 | for i=1:nm 50 | SM(:,i)=M(i)*delta(:,i); 51 | end 52 | 53 | num_coa = sum(SM,2); 54 | den_coa = sum(M); 55 | delta_coa = num_coa/den_coa; 56 | 57 | for i=1:nm 58 | Jg(:,i)=M(i)*(delta(:,i)-delta_coa).^2; 59 | Jcoa(:,i)=trapz(t,Jg(:,i)); 60 | end 61 | 62 | 63 | Mtot = sum(M); 64 | T = nt; 65 | Jtot = sum(Jcoa); 66 | MT = 1/(Mtot*T); 67 | J1 = MT*Jtot; 68 | 69 | J=J1/nm; 70 | 71 | -------------------------------------------------------------------------------- /_source/v0_2_iTeslaUpdate/3 Dynamic Transient/transient.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_2_iTeslaUpdate/3 Dynamic Transient/transient.mat -------------------------------------------------------------------------------- /_source/v0_2_iTeslaUpdate/4 Dynamic_SmallSignal_v1.2/7bus_fault.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_2_iTeslaUpdate/4 Dynamic_SmallSignal_v1.2/7bus_fault.mat -------------------------------------------------------------------------------- /_source/v0_2_iTeslaUpdate/4 Dynamic_SmallSignal_v1.2/Dynamic_smallsignal_example.m: -------------------------------------------------------------------------------- 1 | clear all;clc;close all 2 | 3 | %% Load time series 4 | 5 | load 7bus_fault % The 7 bus system 6 | % load KTH_Nordic32_fault % The Nordic power system 7 | 8 | 9 | %% Set input parameters and call main function 10 | 11 | time = ts; % Time vector of order Nx1 with variable time step 12 | signal = P_line; % Active power flow on relevant lines of order NxM, where M is the number of signals 13 | 14 | step_min = 0.04; % Minimum step size (full details in future documentation) 15 | var_min = 0.1;%0.3; % [0-1] Filter signals with varianza smaller than "var_min" 16 | f = [0.1,2.5]; % [fmin,fmax] Range of frequencies of interest in Hz 17 | d =[0,5,10]; % Damping values in percent (%) where the index distances will be calculated 18 | Nm =10; % Number of modes used in Prony to reconstruct the signals 19 | 20 | [ss,y0,G,det]=sssi(signal,time,step_min,var_min,f,d,Nm); 21 | 22 | ss.smi 23 | ss.ami 24 | ss.gmi 25 | 26 | %% Outputs 27 | % 28 | % ss is a structure with the actual small-signal-stability index 29 | % ss.smi single mode indicator 30 | % ss.ami all modes indicator 31 | % ss.gmi global mode indicator 32 | % 33 | % y0 is a structure with the section of signals that where used as input in Prony 34 | % y0.t time vector 35 | % y0.y signals 36 | % 37 | % G is a structure with Prony output 38 | % G.Poles detected modes 39 | % G.Res residue of each mode 40 | % G.K gain of each mode 41 | % G.that time vector 42 | % G.yhat re-constructed signal 43 | % 44 | % det is a structure summarizing information 45 | % det.l Complex value of detected modes in the range of frequency 46 | % det.f Frequency in Hz of modes 47 | % det.d Damping in percent of modes -------------------------------------------------------------------------------- /_source/v0_2_iTeslaUpdate/4 Dynamic_SmallSignal_v1.2/KTH_Nordic32_fault.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_2_iTeslaUpdate/4 Dynamic_SmallSignal_v1.2/KTH_Nordic32_fault.mat -------------------------------------------------------------------------------- /_source/v0_2_iTeslaUpdate/4 Dynamic_SmallSignal_v1.2/Main_quinary_french_test.m: -------------------------------------------------------------------------------- 1 | clear all;clc;close all 2 | addpath 'H:\KTH-Postdoc 2013\iTesla\WP4\Indexes_review\20130115_1845_SN2_FR0' 3 | 4 | %% Load time series 5 | 6 | load sim_fault_0_smallsignal.mat 7 | % load sim_fault_1_smallsignal.mat 8 | % load sim_fault_2_smallsignal.mat 9 | % load sim_fault_3_smallsignal.mat 10 | % load sim_fault_4_smallsignal.mat 11 | % load sim_fault_5_smallsignal.mat 12 | % load sim_fault_6_smallsignal.mat 13 | % load sim_fault_7_smallsignal.mat 14 | 15 | figure;plot(t,LP1);axis tight 16 | return 17 | %% Set input parameters and call main function 18 | 19 | time = t; % Time vector of order Nx1 with variable time step 20 | signal = LP1; % Active power flow on relevant lines of order NxM, where M is the number of signals 21 | 22 | %step_min = 0.04; % Minimum step size (full details in future documentation) 23 | %var_min = 0.1%0.3; % [0-1] Filter signals with varianza smaller than "var_min" 24 | %f = [0.1,2.5]; % [fmin,fmax] Range of frequencies of interest in Hz 25 | %d =[0,5,10]; % Damping values in percent (%) where the index distances will be calculated 26 | %Nm =10; % Number of modes used in Prony to reconstruct the signals 27 | 28 | [ss,y0,G,det]=sssi(signal,time,step_min,var_min,f,d,Nm); 29 | 30 | ss.smi 31 | ss.ami 32 | ss.gmi 33 | 34 | %% Outputs 35 | % 36 | % ss is a structure with the actual small-signal-stability index 37 | % ss.smi single mode indicator 38 | % ss.ami all modes indicator 39 | % ss.gmi global mode indicator 40 | % 41 | % y0 is a structure with the section of signals that where used as input in Prony 42 | % y0.t time vector 43 | % y0.y signals 44 | % 45 | % G is a structure with Prony output 46 | % G.Poles detected modes 47 | % G.Res residue of each mode 48 | % G.K gain of each mode 49 | % G.that time vector 50 | % G.yhat re-constructed signal 51 | % 52 | % det is a structure summarizing information 53 | % det.l Complex value of detected modes in the range of frequency 54 | % det.f Frequency in Hz of modes 55 | % det.d Damping in percent of modes -------------------------------------------------------------------------------- /_source/v0_2_iTeslaUpdate/4 Dynamic_SmallSignal_v1.2/pronyiTesla.m: -------------------------------------------------------------------------------- 1 | function [lamda,model]=pronyiTesla(t,y,XX,tstart,tend,T,shift,tstplot,tedplot,plotFlag); 2 | %[model]=pronyanalysis(t,y,n,tstart,tend,T,shift,tstplot,tedplot,plotFlag); 3 | %Prony analysis program for fitting to a ringdown 4 | % Inputs: 5 | % t = time vector (does not need to be equally spaced) -- column vector 6 | % t(1) is assumed to be 0; if not, all time variables are shifted by t(1). 7 | % y = ringdown matrix of order N by NChan corresponding to t, each column is a different signal 8 | % n = order of the estimated model 9 | % tstart = row vector of order 1 by NChan. tstart(k) is the starting 10 | % time for analysis for y(:,k). 11 | % tend = ending times for analysis (same dimension as tstart) 12 | % shift = flag; if shift = 1, residues are shifted to t = 0. 13 | % If the data is noisy, reccomend shift = 0. 14 | % T = sample period for analysis 15 | % tsttplot = starting time for model simulation 16 | % tedplot = ending time for model simulation 17 | % plotFlag = if = 1, plot results 18 | % Outputs (structured array): 19 | % model.Poles = ringdown pole matrix -- column k is for column k of y 20 | % model.Res = ringdown residue matrix 21 | % model.K = ringdown offset row vector 22 | % model.yhat = model signal matrix 23 | % model.that = time vector for yhat (starts at tstart) 24 | % 25 | % NOTE: It is reccomended that the N/(1+NChan) < 200, where 26 | % N = total number of data points in y to be analyzed, and 27 | % NChan = number of columns in y. 28 | 29 | % Written by D. Trudnowski, 1999. 30 | % Last update, D. Trudnowski, 2005. 31 | 32 | % 1.0 Setup 33 | 34 | %Basic error checks 35 | 36 | if (size(y,2)~=size(tstart,2))|(size(y,2)~=size(tend,2)); error('Dimension error in y, tstart, tend'); end; 37 | if (size(tstart,1)~=1)|(size(tend,1)~=1); error('Dimension error in tstart or tend'); end; 38 | if (T<=0)|(tstplot>=tedplot)|(max(t)min(tstart')); error('data error'); end; 39 | if (size(t,1) ~= size(y,1))|(size(t,2)~=1); error('Dimension error in y or t'); end; 40 | 41 | %Data parameters 42 | NChannels = size(y,2); 43 | 44 | %Shift time parameters 45 | tstart = tstart-t(1); 46 | tend = tend-t(1); 47 | tstplot = tstplot-t(1); 48 | tedplot = tedplot-t(1); 49 | t = t-t(1); 50 | 51 | %Set up analysis data and calculate offset 52 | tanalysis = T*[0:1:ceil(max(tend')/T)+1]'; 53 | Nstart = zeros(1,NChannels); 54 | Nend = zeros(1,NChannels); 55 | yanal = zeros(length(tanalysis),NChannels); 56 | K = zeros(1,NChannels); 57 | for k=1:NChannels 58 | Nstart(k) = floor(tstart(k)/T)+1; 59 | Nend(k) = ceil(tend(k)/T)+1; 60 | yanal(:,k) = spline(t,y(:,k),tanalysis); 61 | K(1,k) = mean(yanal(Nstart(k):Nend(k),k)); 62 | yanal(:,k) = yanal(:,k)-K(k); 63 | end 64 | clear k 65 | 66 | %Find model order 67 | NdataPoints = Nend-Nstart+1; %Number of data points used for analysis on each channel 68 | Ntotal = sum(NdataPoints'); %Total number of data points used for Prony analysis 69 | %nOrder = round(Ntotal/(1+NChannels))-10; %Order of Linear Prediction 70 | nOrder=XX; 71 | %if (nOrder>50); nOrder=50; end; %Limit order to avoid numerical problems 72 | 73 | % 2.0 Solve Linear Prediction 74 | 75 | %Build matrix and vector 76 | for k=1:NChannels 77 | Ym = zeros(NdataPoints(k)-nOrder,nOrder); 78 | for kk=1:nOrder 79 | Ym(:,kk) = yanal(Nstart(k)+nOrder-kk:Nstart(k)-kk+NdataPoints(k)-1,k); 80 | end 81 | yv = yanal(Nstart(k)+nOrder:Nstart(k)+NdataPoints(k)-1,k); 82 | if k==1; 83 | Ymatrix = Ym; 84 | yvector = yv; 85 | else 86 | Ymatrix = [Ymatrix;Ym]; %Cancatinate the channels 87 | yvector = [yvector;yv]; 88 | end 89 | end 90 | clear Ym yv k kk 91 | % acoef = pinv(Ymatrix)*yvector; %characteristic eqn. Pseudo inverse using SVD 92 | acoef = Ymatrix\yvector; %This provides a much more accurate solution than the above line 93 | 94 | %Find poles 95 | zPoles = roots([1;-acoef]); 96 | sPoles = log(zPoles)/T; 97 | 98 | 99 | 100 | % 3.0 Solve for residues 101 | Res = zeros(nOrder,NChannels); 102 | for k=1:NChannels 103 | ZMatrix = zeros(NdataPoints(k),nOrder); 104 | for kk=1:NdataPoints(k) 105 | ZMatrix(kk,:) = (zPoles.').^(kk-1); 106 | end 107 | Res(:,k) = ZMatrix\yanal(Nstart(k):Nend(k),k); 108 | if shift==1; 109 | Res(:,k) = Res(:,k).*(zPoles.^(-Nstart(k)+1)); %Shift residues to time 0 110 | end 111 | end 112 | clear k kk 113 | 114 | % 4.0 Re-order using energy 115 | P = zeros(nOrder,NChannels); 116 | R = zeros(size(Res)); 117 | for k=1:NChannels 118 | clear E 119 | for kk=1:nOrder 120 | if abs(real(sPoles(kk)))<1e-8 121 | E(kk)=Res(kk,k)^2*(tend(k)-tstart(k)); 122 | else 123 | E(kk)=(Res(kk,k)^2/(2*real(sPoles(kk))))*(exp(2*real(sPoles(kk))*(tend(k)-tstart(k)))-1); 124 | end 125 | end 126 | E=E(:); 127 | [x,ii]=sort(E); 128 | R(:,k)=Res(ii,k); 129 | P(:,k)=sPoles(ii); 130 | M=[length(ii):-1:1]'; 131 | R(:,k)=R(M,k); 132 | P(:,k)=P(M,k); 133 | end 134 | clear M k x ii E 135 | 136 | %Simulate; 137 | that = [tstplot:T:tedplot]'; 138 | yhat = zeros(length(that),NChannels); 139 | for k=1:NChannels 140 | yhat(:,k) = K(k).*ones(size(that)); 141 | for kk=1:length(that); 142 | for n=1:nOrder; 143 | yhat(kk,k) = yhat(kk,k) + R(n,k)*exp(P(n,k)*that(kk)); 144 | end 145 | end; 146 | end; 147 | yhat=real(yhat); 148 | 149 | % 5.0 Place output in structured array 150 | model.Poles = P; 151 | model.Res = R; 152 | model.K = K; 153 | model.that = that; 154 | model.yhat = yhat; 155 | 156 | lamda=sPoles; 157 | 158 | 159 | 160 | % 6.0 Plot results 161 | if plotFlag==1 162 | figure 163 | hold on 164 | h1 = plot(t,y); 165 | h2 = plot(that,yhat,'--*');axis tight 166 | hold off 167 | xlabel('Time (sec)') 168 | %legend('Actual','Prony') 169 | end 170 | 171 | %Original plots 172 | % if plotFlag==1 173 | % for k=1:size(yhat,2) 174 | % figure 175 | % n = find(t(t>=tstplot&t<=tedplot)); 176 | % hold on 177 | % h1 = plot(t(n),y(n,k),'k','linewidth',1.5); 178 | % h2 = plot(that,yhat(:,k),'r--','linewidth',1.5); 179 | % hold off 180 | % xlabel('Time (sec)') 181 | % legend('Actual','Prony') 182 | % end 183 | % end -------------------------------------------------------------------------------- /_source/v0_2_iTeslaUpdate/4 Dynamic_SmallSignal_v1.2/pronyiTesla.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_2_iTeslaUpdate/4 Dynamic_SmallSignal_v1.2/pronyiTesla.p -------------------------------------------------------------------------------- /_source/v0_2_iTeslaUpdate/4 Dynamic_SmallSignal_v1.2/signal_filter.m: -------------------------------------------------------------------------------- 1 | function [ yh,osc_signal, var_s,ydh ] = signal_filter(sig,t,var_thr,step_min) 2 | % [Yh,IDX,VAR ]= signal_filter(Y,T,Thr) 3 | % Filter signal Y based on variance. The signals with threshold lower than Thr are removed. 4 | % The time vector T is required, which has variable step size. The output of the function are: 5 | % Yh- Output signal after filter 6 | % IDX- indexes of the most relevant signals 7 | % VAR-Variance of signals Y. 8 | % 9 | % If no oscillation is detected, the function gives empty matrices. 10 | 11 | 12 | 13 | nL = size(sig,2); % number of signals 14 | ts = t; % time vector with variable step 15 | trshold=var_thr; % select signals with variance higher than var_thr 16 | tsmin= step_min; % select section of signal with step size grater than step_min 17 | 18 | %% Identify disturbance on time-series with variable step 19 | 20 | tk=zeros(size(ts)); 21 | tq=zeros(size(ts)); 22 | tk(2:end)=ts(1:end-1); 23 | tm=ts-tk; 24 | tm(1)=0; %remove first element 25 | tq(3:end)=tm(2:end-1); 26 | h=tm-tq; 27 | n=size(tm,1); 28 | tr=[1:1:n]'; % line improved 29 | 30 | %figure;plot(tr,tm) 31 | 32 | hmax=max(h); 33 | 34 | jj=1; qq=1; ta=zeros(size(tm)); 35 | 36 | for i=1:n-1, 37 | ta(jj,:,qq)=tm(i); 38 | thr0(i,1)=tm(i)-tm(i+1); % 39 | if tm(i)>hmax 40 | qq=qq+1; 41 | end 42 | jj=jj+1; 43 | end 44 | 45 | p=size(ta,3); 46 | ll=size(ta,1); 47 | jj=1; 48 | tw=[];tu=[]; 49 | yy=1; 50 | pp=1; ww=0; gg=0; 51 | 52 | for i=1:p, 53 | 54 | for k=1:ll; 55 | 56 | if ta(k,:,i)>=0.0001 57 | tw(jj,1)=ta(k,:,i); 58 | tw(jj,2)=k; 59 | jj=jj+1; 60 | end 61 | 62 | if k==ll 63 | nx=size(tw,1); 64 | nm(i,1)=size(tw,1)-gg; 65 | gg=sum(nm); 66 | end 67 | 68 | end 69 | 70 | 71 | for a=yy:nx 72 | 73 | if tw(a,1)<=0.20 74 | tu(pp,1)=tw(a,1); 75 | tu(pp,2)=tw(a,2); 76 | pp=pp+1; 77 | end 78 | 79 | if a==nx 80 | jo(i,1)=size(tu,1)-ww; 81 | ww=sum(jo); 82 | end 83 | 84 | end 85 | 86 | yy=a+1; 87 | 88 | 89 | 90 | end 91 | 92 | 93 | %% Signal selection according to variance 94 | 95 | 96 | time=[]; signal=[]; osc_signal=[]; 97 | for i=1:p 98 | if jo(i)>1e-3 99 | Var(i,:)=var(sig(tu(sum(jo(1:i-1))+1,2):tu(sum(jo(1:i)),2),:)); 100 | Var_t(i,1)=sum(Var(i,:)); %Variance total 101 | if Var_t(i,1)>0.01; 102 | time=ts(tu(sum(jo(1:i-1))+1,2):tu(sum(jo(1:i)),2),:); 103 | signal=sig(tu(sum(jo(1:i-1))+1,2):tu(sum(jo(1:i)),2),:); 104 | 105 | end 106 | end 107 | end 108 | 109 | if isempty(time) 110 | osc_signal=[]; 111 | var_s=[]; 112 | yh=[]; 113 | ydh=[]; 114 | fprintf('\n Signals not suitable for SSS analysis! \n\n') 115 | else 116 | j0=1; 117 | time0=zeros(size(time)); 118 | time0(1)=time(1); 119 | time0(2:end)=time(1:end-1); 120 | dt0 =time-time0; 121 | gg=size(time,1); 122 | timex=[]; signalx=[]; 123 | for k=1:gg 124 | if dt0(k)>=tsmin 125 | dt0x(j0,1)=dt0(k); 126 | timex(j0,1)=time(k); 127 | signalx(j0,:)=signal(k,:); 128 | j0=j0+1; 129 | end 130 | end 131 | 132 | if isempty(signalx) 133 | else 134 | for k=1:nL, 135 | signalx0(:,k)=signalx(:,k)-mean(signalx(:,k)); 136 | end 137 | ydh=[timex,signalx0]; 138 | sig_var=var(signalx0)'; % variance 139 | sig_std=std(signalx0)'; % standard deviation 140 | [ var_sort,s_idx]=sort(sig_var,'descend'); 141 | [ std_sort,std_idx]=sort(sig_std,'descend'); 142 | 143 | nL0=size(var_sort,1); 144 | vA=max(var_sort); 145 | var_sort0=var_sort/vA; 146 | 147 | for k=1:nL 148 | if var_sort0(k)>= trshold; 149 | osc_signal(k,1)=s_idx(k); 150 | var_s(k,1)=var_sort(k); 151 | end 152 | end 153 | end 154 | 155 | 156 | if isempty(osc_signal) 157 | osc_signal=[]; 158 | var_s=[]; 159 | yh=[]; 160 | ydh=[]; 161 | fprintf('\n Signals no suitable for SSS analysis! \n\n') 162 | else 163 | 164 | 165 | 166 | yh=sig(:,osc_signal); 167 | 168 | 169 | % figure;plot(ts,sig(:,osc_signal)); 170 | % title(['Sigansl witht oscillation higher than the threshold (',num2str(trshold),')']) 171 | % xlabel('Time (sec)') 172 | end 173 | end 174 | 175 | -------------------------------------------------------------------------------- /_source/v0_2_iTeslaUpdate/4 Dynamic_SmallSignal_v1.2/sssi.m: -------------------------------------------------------------------------------- 1 | function [ sss,out,modelb,detail ] = sssi( signal,ts,stepsize_min,variance_min,Freq,Damp,Nm) 2 | %Small-signal-stability index (SSI) function 3 | % 4 | %[ INDEX ] = sssi( signal,ts,step_min,var_min,F,D,Nm) 5 | % 6 | % OUTPUTS 7 | % 8 | % INDEX - Three layer sss index with smi, ami and gmi. 9 | % 10 | % INPUTS 11 | % signal - Active power flow of relevant lines 12 | % ts - Time vector with varable step size 13 | % step_min - Minimum varable step for signal analysis 14 | % var_min - Filter signals with varianza lower than var_min 15 | % F - [fmin,fmax] 1x2 vector with frequencies of interest in Hz 16 | % D - [d0,d1,d2] 1x3 vector with damping ratios to compute index in 17 | % percent 18 | % Nm - Number of modes used in Prony to reconstruc input signals 19 | % 20 | % 21 | % * Empty matrices will be delivered if input signals used are not 22 | % suitable for sss analysis 23 | 24 | 25 | [yh,x,l,yhd]=signal_filter(signal,ts,variance_min,stepsize_min); 26 | 27 | if isempty(yhd) 28 | out=[]; 29 | sss.smi=[]; 30 | sss.ami=[]; 31 | sss.gmi=[]; 32 | modelb=[]; 33 | detail.l=[]; 34 | detail.f=[]; 35 | detail.d=[]; 36 | else 37 | 38 | t = yhd(:,1); 39 | y = yhd(:,x+1); 40 | 41 | figure;plot(t,y); 42 | 43 | out.t =t; 44 | out.y =y; 45 | 46 | %% 47 | fmin= Freq(1); % Remove frequencies less than fmin Hz 48 | fmax= Freq(2); % Remove frequencies greater than fmax Hz 49 | dmax=0.25; % Remove modes with damping greater than dmax 50 | Nm; % Number of modes used to reconstruct signals using Prony 51 | 52 | sig=y(:,:); 53 | nL=size(sig,2); 54 | 55 | [lamda,modelb]=pronyiTesla(t,sig,Nm,t(1)*ones(1,nL),t(end)*ones(1,nL),0.1,1,t(1),t(end),1); 56 | 57 | Poles.sys=diag(lamda); 58 | 59 | n_modes1 = size(lamda,1); %number of modes 60 | fmodes0 = abs(imag(lamda))/2/pi; % frequency of modes in Hz 61 | dmodes0 = -cos(atan2(imag(lamda),real(lamda))); %damping of modes 62 | 63 | [fmodes1,mode_idx1]=sort(fmodes0,'ascend'); %sorted frequencies 64 | dmodes1=dmodes0(mode_idx1); %sorted dampings 65 | 66 | jj=1; kk=1; 67 | for i=1:n_modes1, 68 | 69 | if (fmodes1(i)>=fmin)&(fmodes1(i)<=fmax) %modes within fmin and fmax 70 | fmodes2(jj,1)=fmodes1(i); 71 | dmodes2(jj,1)=dmodes1(i); 72 | mode_idx2(jj,1)=mode_idx1(i); 73 | if dmodes2(jj,1)<=dmax % discard modes with large damping ratio 74 | fmodes3(kk,1)=fmodes2(jj); 75 | dmodes3(kk,1)=dmodes2(jj); 76 | mode_idx3(kk,1)=mode_idx2(jj); 77 | kk=kk+1; 78 | end 79 | jj=jj+1; 80 | end 81 | 82 | end 83 | 84 | n_modes2=size(fmodes3,1); 85 | jj=[1:2:n_modes2]'; 86 | fmodes=fmodes3(jj); 87 | dmodes=dmodes3(jj); 88 | 89 | fprintf('\n f(Hz) d(%%) \n') 90 | fprintf('--------------') 91 | for i=1:n_modes2/2 92 | fprintf('\n%-7.3f %-7.3f ',fmodes(i),dmodes(i)*100) 93 | end 94 | fprintf('\n\n') 95 | 96 | detail.l=lamda(mode_idx3); 97 | detail.f=fmodes0(mode_idx3); 98 | detail.d=dmodes0(mode_idx3); 99 | 100 | 101 | %% Actual Three layer index SMI, AMI, GMI 102 | 103 | %Damp=[0,5,10]; % Damping ratios, Calculate damping distance from each mode to the specified dampings, ie [0%, 5%, 10%] 104 | 105 | th = acos(Damp/100); 106 | ths = pi-th; 107 | 108 | thl = acos(dmodes); 109 | thls = pi-thl; 110 | 111 | jj=1; kk=size(Damp,2); 112 | for i=1:1:n_modes2/2 113 | for m=1:1:kk 114 | SMI(jj,m)=thls(i)-ths(m); % Matrix, Single Mode Indicator(SMI) in rads 115 | end 116 | jj=jj+1; 117 | end 118 | 119 | for m=1:kk 120 | AMI(1,m)=min(SMI(:,m)); %Vector, All Mode Indicator (AMI) in rads 121 | end 122 | 123 | 124 | GMI=min(AMI); % Gain, Global Mode Indicator (GMI) in rads 125 | 126 | sss.smi = SMI; 127 | sss.ami = AMI; 128 | sss.gmi = GMI; 129 | 130 | end 131 | end 132 | 133 | -------------------------------------------------------------------------------- /_source/v0_3_Nara/01_Static_Overload/Over_Load.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_3_Nara/01_Static_Overload/Over_Load.mat -------------------------------------------------------------------------------- /_source/v0_3_Nara/01_Static_Overload/Overload-1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_3_Nara/01_Static_Overload/Overload-1.mat -------------------------------------------------------------------------------- /_source/v0_3_Nara/01_Static_Overload/Overload-2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_3_Nara/01_Static_Overload/Overload-2.mat -------------------------------------------------------------------------------- /_source/v0_3_Nara/01_Static_Overload/Overload-3.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_3_Nara/01_Static_Overload/Overload-3.mat -------------------------------------------------------------------------------- /_source/v0_3_Nara/01_Static_Overload/Static Overload Indexes.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_3_Nara/01_Static_Overload/Static Overload Indexes.docx -------------------------------------------------------------------------------- /_source/v0_3_Nara/01_Static_Overload/static_overload.m: -------------------------------------------------------------------------------- 1 | 2 | function [Over_S,i2h,ridh,F,f,G,g,steady_state_lines]=static_overload(t,S1,p_1,dev0,deltime,simTime) 3 | %% Post-fault Over Load Index 4 | % This index is used to observe if the post-fault flows surpass the network capacity, 5 | % by monitoring the power flows through the transmission lines right after an outage occurs. 6 | % 7 | % 8 | % [Sindex]=static_overload(t,t1,Signal,w,p,d); 9 | % 10 | % INPUTS 11 | % t - Time vector 12 | % S - Apparent power flow 13 | % p - Exponent 14 | % d - Deviation allowed of power flow from nominal value, e.g. 10 for +10% 15 | % 16 | % OUTPUTS 17 | % Sindex -Overload index 18 | % 19 | % Version 1.2 20 | 21 | 22 | %% OVERLOAD 23 | pre0 = 5; 24 | post0 = 100; 25 | 26 | dev0 = dev0/100; 27 | nl = size(S1,2); 28 | wf_i = ones(1,nl); % Uniform weights in all Lines is assumed 29 | Snom = mean(S1(1:pre0,:)); % Nominal value (pre-contingency) 30 | Smax = Snom*(1+dev0); % Over power flow limits 31 | Spost = S1(end-post0:end,:); 32 | Smean = mean(Spost); 33 | 34 | % Remove lines out of service 35 | xxx=[];k=1; 36 | for i=1:nl 37 | if abs(Smean(1,i))<1e-2 38 | xxx(k,1)=i; 39 | S1(:,i)=0; 40 | Smean(1,i)=0; 41 | Snom(1,i)=0; 42 | k=k+1; 43 | end 44 | end 45 | clear k 46 | 47 | k=1; over_line=[]; 48 | for i=1:nl 49 | indxs_loc=(wf_i(i)*((abs(Smean(1,i))/abs(Smax(1,i)))^p_1)); 50 | index_red(i)=indxs_loc; 51 | 52 | 53 | if indxs_loc>=1 54 | indx(i)=indxs_loc; 55 | over_line(k)=i; % indices of lines violating limits 56 | k=k+1; 57 | else 58 | indx(i)=1; 59 | end 60 | 61 | 62 | rid(i,1) = index_red(i).^(1/p_1); 63 | if rid(i)<=1 64 | ridh(i,1)=1; 65 | i2h(i,1)=1; 66 | else 67 | ridh(i,1)= rid(i); 68 | i2h(i,1)=index_red(i); 69 | end 70 | 71 | end 72 | for i=1:size(rid) 73 | Fx(i)=rid(i); 74 | FFx(i)=i; 75 | end 76 | F=[FFx;Fx]; 77 | F=F'; 78 | Overloaded_lines=over_line'; 79 | for i=1:size(Overloaded_lines) 80 | fx(i)=ridh(Overloaded_lines(i)); 81 | ffx(i)=Overloaded_lines(i); 82 | end 83 | f=[ffx;fx]; 84 | f=f'; 85 | Over_S=sum(i2h)/nl; 86 | 87 | %% Plotting results (if required) 88 | % if Over_S>=1 89 | % nvl=size(over_line,2); %Number of lines violating the limits 90 | % Sextra_pu= indx(over_line)/max(indx(over_line)); 91 | % for i=1:nvl 92 | % if indx(over_line(i)).^(1/p_1)<=2 93 | % indx_over_per(i,1)=((indx(over_line(i)).^(1/p_1))-1)*100; 94 | % else 95 | % indx_over_per(i,1)=((indx(over_line(i)).^(1/p_1)))*100; 96 | % end 97 | % end 98 | % 99 | % if nvl>=1 100 | % 101 | % figure;bar(Smean(1,over_line),'g');hold on;bar(Smax(1,over_line),'y'); legend('S_{mean}','S_{max_{limit}}') 102 | % xlabel('Line Number');ylabel('MVA'); title(['Lines violating the limits=',num2str(nvl)]); 103 | % set(gca,'XTick',[1:nvl]) 104 | % set(gca,'XTickLabel',over_line) 105 | % 106 | % figure;bar(Sextra_pu,'r') 107 | % rr=find(indx==max(indx)); 108 | % title(['Line ',num2str(rr),' with maximum violation of ',num2str(max(indx_over_per)),'% more']) 109 | % set(gca,'XTick',[1:nvl]) 110 | % set(gca,'XTickLabel',over_line) 111 | % 112 | % figure;plot(t,S1(:,rr));axis tight;title(['Line number ', num2str(rr),' with maximum violation']) 113 | % hold on; plot(t(end-post0:end),S1(end-post0:end,rr),'linewidth',3) 114 | % hold on; horline(t,Smax(:,rr),'k:');hold on; horline(t,mean(Spost(:,rr)),'r') 115 | % xlabel('Time (sec)'); ylabel('MVA') 116 | % end 117 | % 118 | % end 119 | %% 120 | t1=simTime-3*deltime; 121 | t2=simTime-2*deltime; 122 | t3=simTime-deltime; 123 | t4=simTime; 124 | S=S1; 125 | lines=size(S); 126 | 127 | % Sampling three equal intervals towards the end of the simulation for 'k-th' line 128 | for k=1:lines(2) 129 | count1=0;count2=0;count3=0; 130 | for i=1:length(t) 131 | if(t(i)>t1 && t(i)<=t2) 132 | count1=count1+1; 133 | SS1(count1,k)=S(i,k); 134 | tt1(count1,k)=t(i); 135 | else if (t(i)>t2 && t(i)<=t3) 136 | count2=count2+1; 137 | SS2(count2,k)=S(i,k); 138 | tt2(count2,k)=t(i); 139 | else if (t(i)>t3 && t(i)<=t4) 140 | count3=count3+1; 141 | SS3(count3,k)=S(i,k); 142 | tt3(count3,k)=t(i); 143 | end 144 | end 145 | end 146 | end 147 | 148 | % Calculating the slopes of the intervals for 'k-th' line 149 | for i=2:count1 150 | Slope1(i-1,k)=(SS1(i,k)-SS1(i-1,k))/(tt1(i,k)-tt1(i-1,k)); 151 | if Slope1(i-1,k)== Inf || Slope1(i-1,k)==-Inf 152 | Slope1(i-1,k)=0; 153 | end 154 | end 155 | 156 | for i=2:count2 157 | Slope2(i-1,k)=(SS2(i,k)-SS2(i-1,k))/(tt2(i,k)-tt2(i-1,k)); 158 | if Slope2(i-1,k)== Inf || Slope2(i-1,k)==-Inf 159 | Slope2(i-1,k)=0; 160 | end 161 | end 162 | 163 | for i=2:count3 164 | Slope3(i-1,k)=(SS3(i,k)-SS3(i-1,k))/(tt3(i,k)-tt3(i-1,k)); 165 | end 166 | 167 | % Calculation of mean slope of the interval for 'k-th' line 168 | mean_slope(1,k)=mean(Slope1(:,k)); 169 | mean_slope(2,k)=mean(Slope2(:,k)); 170 | mean_slope(3,k)=mean(Slope3(:,k)); 171 | 172 | % Calculation of slope variation between the intervals for 'k-th' line 173 | slope_change1(k,1)=(mean_slope(2,k)-mean_slope(1,k)); 174 | slope_change1(k,2)=(mean_slope(3,k)-mean_slope(2,k)); 175 | 176 | % Calculation of the difference between the slope variation for 'k-th' line 177 | variation(k,1)=(abs(slope_change1(k,2)-slope_change1(k,1))); 178 | end 179 | 180 | % Assigning all the lines to an array 181 | for m=1:lines(2) 182 | mm(m,1)=m; 183 | end 184 | 185 | G=[mm variation]; % Matrix with slope variation of all lines 186 | 187 | c1=0; %counting variable 188 | % loop to find the lines in which the power change/variation is high 189 | for i=1:lines(2) 190 | if (variation(i)>2.5) 191 | c1=c1+1; 192 | GG(c1,1)=variation(i); 193 | gg(c1,1)=mm(i); 194 | end 195 | end 196 | % if all lines reaches steady state then setting g to zero 197 | if c1>0 198 | g=[gg,GG]; 199 | else 200 | g=[0,0]; 201 | end 202 | [mm slope_change1]; 203 | [mm variation]; 204 | % figure;plot(slope_change1(:,1),'-ob'); 205 | % hold on;plot(slope_change1(:,2),'-or'); 206 | % Finding the lines in which reached steady state 207 | Slines=0; % variable to count the lines which reached steady state 208 | for i=1:lines(2) 209 | if (slope_change1(i,1)>0 && slope_change1(i,2)<0 || abs(slope_change1(i,2))<=abs(slope_change1(i,1)) && variation(i,1)<0.01) 210 | Slines=Slines+1; 211 | steady_state_lines(Slines,1)=i; 212 | end 213 | end 214 | if Slines==0 215 | steady_state_lines=0; 216 | end 217 | 218 | end -------------------------------------------------------------------------------- /_source/v0_3_Nara/01_Static_Overload/static_overload_index_testing.m: -------------------------------------------------------------------------------- 1 | clear all;clc;close all 2 | 3 | %% Load time series 4 | 5 | load Over_Load 6 | %load Overload-1 7 | %load Overload-2 8 | %load Overload-3 9 | %% POST-FAULT OVER LOADS 10 | 11 | t; % Time vector 12 | S = S1; % Input signal, Aparent power (S) size t x N 13 | p = 3; % Exponent used to magnify problems, value between 1 to "inf" 14 | d = 10; % Maximum Variation allowed from the nominal value (in %), e.g, 10 for 10% 15 | simTime=max(t);% Total simulation time of the given data 16 | Faultime=10; % Fault occuring time in the data 17 | deltime=10; %Time period of each sampled interval 18 | 19 | figure;plot(t,S); 20 | 21 | [f_x,i2h,ridh,F,f,G,g,steady_state_lines] = static_overload(t,S,p,d,deltime,simTime); 22 | 23 | f_x 24 | % outputs 25 | % f_x = Final index 26 | % F = Level of loading on each line 27 | % f = Overloaded lines 28 | % G = State of the lines 29 | % g = The lines in which the power flow variation are high 30 | %steady_state_lines= The lines which reached steady state 31 | %% eof -------------------------------------------------------------------------------- /_source/v0_3_Nara/02_Static_UnderOver_Voltage/OverUnder_Voltage.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_3_Nara/02_Static_UnderOver_Voltage/OverUnder_Voltage.mat -------------------------------------------------------------------------------- /_source/v0_3_Nara/02_Static_UnderOver_Voltage/Static voltage Indexes.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_3_Nara/02_Static_UnderOver_Voltage/Static voltage Indexes.docx -------------------------------------------------------------------------------- /_source/v0_3_Nara/02_Static_UnderOver_Voltage/static_voltage.m: -------------------------------------------------------------------------------- 1 | function [V_index,i2h,ridh,Vol_violation,G,g,steady_state_bus]=static_voltage(t,BVm,p_2,dev,deltime,simTime) 2 | %% Post-fault Under/Over Voltage Index 3 | % Index for voltage of the transmission network right after an outage has occurred, 4 | % the index indicates if the voltage (V), surpass the limits of the operational standards 5 | % 6 | % 7 | % [Vindex]=satatic_voltage(t,V,p,d); 8 | % 9 | % INPUTS 10 | % t - Time vector 11 | % V - Voltages vector 12 | % p - Exponent 13 | % d - Deviation allowed of voltage from nominal value, e.g. 2 for +-2% 14 | % 15 | % OUTPUTS 16 | % Vindex -Under/Over voltage index 17 | % 18 | % 19 | % Version 1.1 20 | % 21 | 22 | dev=dev/100; 23 | 24 | 25 | %% The following parameters are used to calculate the index: 26 | pre0 = 5; 27 | post0 = 100; 28 | 29 | 30 | tpost = t(end-post0:end); % Period of time analyzed 31 | Vnom = mean(BVm(1:pre0,:)); % Nominal value (pre-contingency) 32 | Vpost = BVm(end-post0:end,:); % Voltage values post-contingency to be analyzed 33 | Vmin = Vnom*(1-dev); % Under voltage limits 34 | Vmax = Vnom*(1+dev); % Over voltage limits 35 | nb = size(Vnom,2); % Number of buses 36 | wv_i = ones(1,nb); % Uniform weights in all Buses 37 | 38 | 39 | delV = (Vmax - Vmin)/2; %Equation 40 | Vmean = mean(Vpost); %Equation 41 | 42 | 43 | % Remove bus out of service 44 | xxx=[];k=1; 45 | for i=1:nb 46 | if abs(Vmean(1,i))<1e-2 47 | xxx(k,1)=i; 48 | BVm(:,i)=0; 49 | Vmean(1,i)=0; 50 | Vnom(1,i)=0; 51 | Vmin(1,i)=0; 52 | Vmax(1,i)=0; 53 | wv_i(1,i)=0; 54 | k=k+1; 55 | end 56 | end 57 | clear k 58 | 59 | over_vol=0; 60 | %% Calculation of the actual index 61 | 62 | for i=1:nb 63 | 64 | 65 | % Index equation base on average value 66 | indxs =wv_i(1,i)*((abs(Vnom(i)-Vmean(:,i))./delV(i)).^p_2)'; 67 | 68 | 69 | % Applying considerations to understand the value of the index 70 | i2(i,1)=max(indxs); 71 | 72 | 73 | rid(i,1) = i2(i,1).^(1/p_2); 74 | 75 | if rid(i)<=1 76 | ridh(i,1)=1; 77 | i2h(i,1)=1; 78 | 79 | else if (rid(i)>=1) && (rid(i)<=5*(dev*100)) 80 | ridh(i,1)=rid(i); 81 | i2h(i,1)=i2(i); 82 | else 83 | ridh(i,1)= rid(i); 84 | i2h(i,1)=i2(i); 85 | end 86 | end 87 | 88 | if (rid(i)>1) && (rid(i)<5*(dev*100)) 89 | over_vol=over_vol+1; 90 | Vol_violation(over_vol,1)=i; 91 | end 92 | end 93 | 94 | 95 | % Buses with the voltage less/more than the aceptable min/max voltage 96 | 97 | 98 | if over_vol==0 99 | Vol_violation=0; 100 | end 101 | 102 | i2_tot=sum(i2); 103 | 104 | %%%%%%%%%%%% Under/Over Voltage Index %%%%%%%%%%% 105 | V_index = sum(i2h)/(nb); % The actual index normalized 106 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 107 | 108 | 109 | 110 | %% Ploting results 111 | % r1 = find(i2>=1); % index of lines violating limits 112 | % nvl= size(r1,1); % number of lines violating limits 113 | % r2 = (i2).^(1/p_2); 114 | % nvlsevere=0; 115 | % 116 | % if nvl>0 117 | % figure;plot(t,BVm(:,r1));axis tight 118 | % title(['Lines violating limits = ', num2str(nvl),' Index=',num2str(V_index)]) 119 | % xlabel('Time (sec)') 120 | % ylabel('Voltage') 121 | % if nvlsevere>0 122 | % figure;plot(t,BVm(:,r20));axis tight 123 | % title(['Lines (',num2str(nvlsevere), ') violating limits ',num2str(dev*100),' %']) 124 | % xlabel('Time (sec)') 125 | % ylabel('Voltage') 126 | % end 127 | % a= find(i2(r1)==max(i2(r1))); 128 | % mm=r1(1); 129 | % 130 | % figure;plot(t,BVm(:,mm));axis tight 131 | % hold on; plot(t(end-post0:end),BVm(end-post0:end,mm),'linewidth',3) 132 | % hold on; horline(t,Vmin(mm),'k:');horline(t,Vmax(mm),'k:') 133 | % hold on; horline(t,mean(Vpost(:,mm)),'r') 134 | % title(['Line ', num2str(mm),' with maximum violation, v=',num2str(V_index)]) 135 | % xlabel('Time (sec)') 136 | % ylabel('Voltage') 137 | % end 138 | 139 | %% 140 | clear k; 141 | tt1=simTime-3*deltime;tt2=simTime-2*deltime;tt3=simTime-deltime;tt4=simTime; 142 | V=BVm; 143 | for k=1:nb 144 | count1=0;count2=0;count3=0; 145 | for i=1:length(t) 146 | if(t(i,1)>tt1 && t(i,1)<=tt2) 147 | count1=count1+1; 148 | V1(count1,k)=V(i,k); 149 | t1(count1,k)=t(i,1); 150 | else if (t(i,1)>tt2 && t(i,1)<=tt3) 151 | count2=count2+1; 152 | V2(count2,k)=V(i,k); 153 | t2(count2,k)=t(i,1); 154 | else if (t(i,1)>tt3 && t(i,1)<=tt4) 155 | count3=count3+1; 156 | V3(count3,k)=V(i,k); 157 | t3(count3,k)=t(i); 158 | end 159 | end 160 | end 161 | end 162 | % Calculating the slopes of the intervals for 'k-th' bus 163 | for i=2:count1 164 | Slope1(i-1,k)=(V1(i,k)-V1(i-1,k))/(t1(i,k)-t1(i-1,k)); 165 | if Slope1(i-1,k)== Inf || Slope1(i-1,k)==-Inf 166 | Slope1(i-1,k)=0; 167 | end 168 | end 169 | 170 | for i=2:count2 171 | Slope2(i-1,k)=(V2(i,k)-V2(i-1,k))/(t2(i,k)-t2(i-1,k)); 172 | if Slope2(i-1,k)== Inf || Slope2(i-1,k)==-Inf 173 | Slope2(i-1,k)=0; 174 | end 175 | end 176 | 177 | for i=2:count3 178 | Slope3(i-1,k)=(V3(i,k)-V3(i-1,k))/(t3(i,k)-t3(i-1,k)); 179 | if Slope3(i-1,k)== Inf || Slope3(i-1,k)==-Inf 180 | Slope3(i-1,k)=0; 181 | end 182 | end 183 | 184 | % Calculation of mean slope of the interval for 'k-th' bus 185 | mean_slope(1,k)=mean(Slope1(:,k)); 186 | mean_slope(2,k)=mean(Slope2(:,k)); 187 | mean_slope(3,k)=mean(Slope3(:,k)); 188 | 189 | % Calculation of slope variation between the intervals for 'k-th' bus 190 | slope_change1(k,1)=(mean_slope(2,k)-mean_slope(1,k)); 191 | slope_change1(k,2)=(mean_slope(3,k)-mean_slope(2,k)); 192 | 193 | % Calculation of the difference between the slope variation for 'k-th' bus 194 | variation(k,1)=(abs(slope_change1(k,2)-slope_change1(k,1))); 195 | end 196 | % Assigning all the buses to an array 197 | for m=1:nb 198 | buses(m,1)=m; 199 | end 200 | 201 | G=[buses variation]; % Matrix with slope variation of bus voltages 202 | 203 | % loop to find the lines in which the voltage variation is high 204 | c1=0; %counting variable 205 | for i=1:nb 206 | if (variation(i)>1) 207 | c1=c1+1; 208 | GG(c1,1)=variation(i); 209 | gg(c1,1)=buses(i); 210 | end 211 | end 212 | 213 | 214 | % if all voltages reaches steady state then setting g to zero 215 | if c1>0 216 | g=[gg,GG]; 217 | else 218 | g=[0,0]; 219 | end 220 | 221 | % Finding the lines in which reached steady state 222 | SS_bus=0; % variable to count the lines which reached steady state 223 | for i=1:nb 224 | if ( variation(i,1)<=0.001) 225 | SS_bus=SS_bus+1; 226 | steady_state_bus(SS_bus,1)=i; 227 | end 228 | 229 | end 230 | 231 | 232 | 233 | end % function end 234 | 235 | 236 | -------------------------------------------------------------------------------- /_source/v0_3_Nara/02_Static_UnderOver_Voltage/static_voltage_index_testing.m: -------------------------------------------------------------------------------- 1 | % POST-FAULT UNDER/OVER VOLTAGE 2 | 3 | % Sample script 4 | clear all;clc;close all 5 | 6 | %% Load time series 7 | load OverUnder_Voltage 8 | 9 | % POST-FAULT UNDER/OVER VOLTAGE 10 | %% Input data and options into the index 11 | t; % time vector 12 | V = BVm; % Voltage magnitudes - Matrix of size t x N 13 | p = 3; % Exponent used to scale the index, value between 1 to "inf" 14 | d = 1; % Maximum voltage variation allowed (in %) of the nominal value, i.e. 2 for 2% 15 | simTime=max(t); % Total simulation time of the given data 16 | deltime=25; %Time period of each interval 17 | 18 | 19 | % Compute the index 20 | [v_x,i2h,F,f,G,g,Steady_State_buses] = static_voltage(t,V,p,d,deltime,simTime); 21 | 22 | % Display the index in the Command Window 23 | v_x 24 | %% 25 | plot(t,V); 26 | if SS_buses~=0 27 | figure;plot(t,V(:,SS_buses(:,:))) 28 | end 29 | % outputs 30 | % v_x = Final index 31 | % F = voltage level of each bus as per the index calculation 32 | % f = Bus numbers which violated voltage limits 33 | % Steady_State_buses = Bus numbers whose voltages reached steady state 34 | % G = Rate of change of voltage variation of all buses 35 | % g = Buses in high voltage variation 36 | %% eof -------------------------------------------------------------------------------- /_source/v0_3_Nara/03_b_Voltage_Stability_Indexes_single_flow/2bus-system.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_3_Nara/03_b_Voltage_Stability_Indexes_single_flow/2bus-system.mat -------------------------------------------------------------------------------- /_source/v0_3_Nara/03_b_Voltage_Stability_Indexes_single_flow/Estimate.m: -------------------------------------------------------------------------------- 1 | function F = Estimate(z) 2 | 3 | global PP QQ VV 4 | 5 | % Unknown variables, 6 | % one delta variable for each operating point. 7 | n=size(PP,1); 8 | delta = z(1:n); 9 | E = z(n+1); 10 | X = z(n+2); 11 | 12 | % Power Flow Equations 13 | F = [PP*X - E*VV.*sin(delta) 14 | QQ*X - E*VV.*cos(delta) + VV.^2]; -------------------------------------------------------------------------------- /_source/v0_3_Nara/03_b_Voltage_Stability_Indexes_single_flow/Estimate_a_b.m: -------------------------------------------------------------------------------- 1 | function F = Estimate_a_b(z) 2 | global PP QQ 3 | 4 | % Unknown variables, 5 | % one delta variable for each operating point. 6 | 7 | a = z(1); 8 | b = z(2); 9 | 10 | % Power Flow Equations 11 | F = [a+b*PP-QQ]; -------------------------------------------------------------------------------- /_source/v0_3_Nara/03_b_Voltage_Stability_Indexes_single_flow/KTH_Nordic_trip_L32.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_3_Nara/03_b_Voltage_Stability_Indexes_single_flow/KTH_Nordic_trip_L32.mat -------------------------------------------------------------------------------- /_source/v0_3_Nara/03_b_Voltage_Stability_Indexes_single_flow/KTH_Nordic_trip_L42.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_3_Nara/03_b_Voltage_Stability_Indexes_single_flow/KTH_Nordic_trip_L42.mat -------------------------------------------------------------------------------- /_source/v0_3_Nara/03_b_Voltage_Stability_Indexes_single_flow/dynamic_voltagestability_precontingency.m: -------------------------------------------------------------------------------- 1 | function [PPremax1,VPremax1,PPremax2,VPremax2,PPre_pvcurve1,VPre_pvcurve1,PPre_pvcurve2,VPre_pvcurve2,states1,states2,E_pre,X_pre,P1,V1]=dynamic_voltagestability_precontingency(t,P,V,Q,P0,Q0,V0,P2,V2,Q2,faultime,alp,bet,samples) 2 | global PP QQ VV 3 | %Pre-contingency loading conditions 4 | mm=size(V); 5 | for m=1:mm(2) 6 | s=5; 7 | PPre1=zeros(s,m); 8 | VPre1=zeros(s,m); 9 | QPre1=zeros(s,m); 10 | count_pre=0; %counting variable 11 | max=size(t); 12 | 13 | for ii=1:max 14 | if t(ii,1)=0 69 | countP_esti=countP_esti+1; 70 | Vs=[Vs sqrt(Vs2)]; 71 | Vu=[sqrt(E^2/2-Qestim*X-sqrt(E^4/4-X^2*Pmax^2-Qestim*X*E^2)) Vu]; 72 | Pestim=[Pestim Pmax]; 73 | Pmax=Pmax+.01*Pdirection; 74 | else 75 | maxPflag=1; 76 | end 77 | end 78 | for ll=2:countP_esti 79 | if(Pestim(ll)>Pestim(ll-1)) 80 | Pmax=Pestim(ll); 81 | Pmaxindex=ll; 82 | end 83 | end 84 | %--- Save the Pmax and Vmax values ---% 85 | Vmax = Vs(Pmaxindex); 86 | 87 | 88 | %--- Save PV curve data for plots ---% 89 | V_pvcurve= [Vs Vu]; 90 | if Pdirection >= 0 91 | P_pvcurve = [Pestim sort(Pestim,2,'descend')]; 92 | else 93 | P_pvcurve = [Pestim sort(Pestim,2,'ascend')]; 94 | end 95 | 96 | if ii==1 97 | PPremax1(m)=Pmax; 98 | VPremax1(m)=Vmax; 99 | if m==1 100 | PPre_pvcurve1(m,:)=P_pvcurve; 101 | VPre_pvcurve1(m,:)=V_pvcurve; 102 | kk=length(PPre_pvcurve1(m,:)); 103 | else if (m>1 && length(P_pvcurve)==kk) 104 | PPre_pvcurve1(m,:)=P_pvcurve; 105 | VPre_pvcurve1(m,:)=V_pvcurve; 106 | else if (m>1 && length(P_pvcurve)1 && length(P_pvcurve)>kk) 114 | for aa=kk:length(P_pvcurve) 115 | PPre_pvcurve1(m-1,aa)=0; 116 | VPre_pvcurve1(m-1,aa)=0; 117 | end 118 | PPre_pvcurve1(m,:)=P_pvcurve; 119 | VPre_pvcurve1(m,:)=V_pvcurve; 120 | end 121 | end 122 | end 123 | end 124 | clr='-*b'; 125 | k='b'; 126 | w=3; 127 | else 128 | PPremax2(m)=Pmax; 129 | VPremax2(m)=Vmax; 130 | if m==1 131 | PPre_pvcurve2(m,:)=P_pvcurve; 132 | VPre_pvcurve2(m,:)=V_pvcurve; 133 | bb=length(PPre_pvcurve2); 134 | else if(m>1 && length(P_pvcurve)==bb) 135 | PPre_pvcurve2(m,:)=P_pvcurve; 136 | VPre_pvcurve2(m,:)=V_pvcurve; 137 | else if (m>1 && length(P_pvcurve)1 && length(P_pvcurve)>bb) 145 | for aa=bb:length(P_pvcurve) 146 | PPre_pvcurve2(m-1,aa)=0; 147 | VPre_pvcurve2(m-1,aa)=0; 148 | end 149 | PPre_pvcurve2(m,:)=P_pvcurve; 150 | VPre_pvcurve2(m,:)=V_pvcurve; 151 | end 152 | end 153 | end 154 | end 155 | clr='-*g'; 156 | k='g'; 157 | w=1.5; 158 | end 159 | 160 | Pmax0=4;hold on; 161 | plot(PP,VV,clr,'linewidth',w) 162 | hold on (m);plot(PPre(:,m),VPre(:,m),'linewidth',w); 163 | hold on (m);plot(P_pvcurve,V_pvcurve,k); 164 | 165 | legend('actual','estimated') 166 | hold on (m); verline(Pmax,'b') 167 | hold on (m); verline(Pmax-(Pmax*Pmax0)/100,'b:') 168 | end 169 | end 170 | end 171 | -------------------------------------------------------------------------------- /_source/v0_3_Nara/03_b_Voltage_Stability_Indexes_single_flow/hline.m: -------------------------------------------------------------------------------- 1 | function hhh=hline(y,in1,in2) 2 | % function h=hline(y, linetype, label) 3 | % 4 | % Draws a horizontal line on the current axes at the location specified by 'y'. Optional arguments are 5 | % 'linetype' (default is 'r:') and 'label', which applies a text label to the graph near the line. The 6 | % label appears in the same color as the line. 7 | % 8 | % The line is held on the current axes, and after plotting the line, the function returns the axes to 9 | % its prior hold state. 10 | % 11 | % The HandleVisibility property of the line object is set to "off", so not only does it not appear on 12 | % legends, but it is not findable by using findobj. Specifying an output argument causes the function to 13 | % return a handle to the line, so it can be manipulated or deleted. Also, the HandleVisibility can be 14 | % overridden by setting the root's ShowHiddenHandles property to on. 15 | % 16 | % h = hline(42,'g','The Answer') 17 | % 18 | % returns a handle to a green horizontal line on the current axes at y=42, and creates a text object on 19 | % the current axes, close to the line, which reads "The Answer". 20 | % 21 | % hline also supports vector inputs to draw multiple lines at once. For example, 22 | % 23 | % hline([4 8 12],{'g','r','b'},{'l1','lab2','LABELC'}) 24 | % 25 | % draws three lines with the appropriate labels and colors. 26 | % 27 | % By Brandon Kuczenski for Kensington Labs. 28 | % brandon_kuczenski@kensingtonlabs.com 29 | % 8 November 2001 30 | 31 | if length(y)>1 % vector input 32 | for I=1:length(y) 33 | switch nargin 34 | case 1 35 | linetype='r:'; 36 | label=''; 37 | case 2 38 | if ~iscell(in1) 39 | in1={in1}; 40 | end 41 | if I>length(in1) 42 | linetype=in1{end}; 43 | else 44 | linetype=in1{I}; 45 | end 46 | label=''; 47 | case 3 48 | if ~iscell(in1) 49 | in1={in1}; 50 | end 51 | if ~iscell(in2) 52 | in2={in2}; 53 | end 54 | if I>length(in1) 55 | linetype=in1{end}; 56 | else 57 | linetype=in1{I}; 58 | end 59 | if I>length(in2) 60 | label=in2{end}; 61 | else 62 | label=in2{I}; 63 | end 64 | end 65 | h(I)=hline(y(I),linetype,label); 66 | end 67 | else 68 | switch nargin 69 | case 1 70 | linetype='r:'; 71 | label=''; 72 | case 2 73 | linetype=in1; 74 | label=''; 75 | case 3 76 | linetype=in1; 77 | label=in2; 78 | end 79 | 80 | 81 | 82 | 83 | g=ishold(gca); 84 | hold on 85 | 86 | x=get(gca,'xlim'); 87 | h=plot(x,[y y],linetype); 88 | if ~isempty(label) 89 | yy=get(gca,'ylim'); 90 | yrange=yy(2)-yy(1); 91 | yunit=(y-yy(1))/yrange; 92 | if yunit<0.2 93 | text(x(1)+0.02*(x(2)-x(1)),y+0.02*yrange,label,'color',get(h,'color')) 94 | else 95 | text(x(1)+0.02*(x(2)-x(1)),y-0.02*yrange,label,'color',get(h,'color')) 96 | end 97 | end 98 | 99 | if g==0 100 | hold off 101 | end 102 | set(h,'tag','hline','handlevisibility','off') % this last part is so that it doesn't show up on legends 103 | end % else 104 | 105 | if nargout 106 | hhh=h; 107 | end 108 | 109 | 110 | -------------------------------------------------------------------------------- /_source/v0_3_Nara/03_b_Voltage_Stability_Indexes_single_flow/indices_calculation.m: -------------------------------------------------------------------------------- 1 | function [SBI1,ABI1,GBI1,SBI2,ABI2,GBI2,DataPre1,DataPost1,DataPre2,DataPost2]=indices_calculation(PPremax,VPremax,Pmax0_pre,Pmax0_post,Vmax0_pre,P0,P1,P2,V0,V1,V2,P_pvpost,V_pvpost,PPost,VPost,PPostmax,VPostmax,P_pvpre1,V_pvpre1,P_pvpre2,V_pvpre2) 2 | global Lb 3 | for m=1:length(Lb) 4 | for kk=1:2 5 | Plim_pre=PPremax(kk,m)-(Pmax0_pre(m)*PPremax(kk,m))/100 6 | Vlim_pre=VPremax(kk,m)+(Vmax0_pre(m)*VPremax(kk,m))/100; 7 | 8 | Pmean_pre=[P0(1,m);P1;P2(kk,m)] 9 | Vmean_pre=[V0(1,m);V1;V2(kk,m)]; 10 | 11 | PLimits_pre=(Plim_pre-Pmean_pre)/Plim_pre 12 | VLimits_pre=(Vmean_pre-Vlim_pre)/Vlim_pre; 13 | 14 | % For Pre-Contingency PV curve-2 15 | Pmean_post=PPost(:,m) 16 | Vmean_post=VPost(:,m); 17 | 18 | Pmax_post=PPostmax(1,m) 19 | Vmax_post=VPostmax(1,m); 20 | 21 | Plim_post=Pmax_post-(Pmax_post*Pmax0_post(1,m))/100 22 | Vlim_post=Vmax_post+(Vmax_post*Vmax0_pre(1,m))/100; 23 | PLimits_post=(Plim_post-Pmean_post)/Plim_post; 24 | VLimits_post=(Vmean_post-Vlim_post)/Vlim_post; 25 | %% 26 | lmax=1.0; 27 | lmin=0.9; 28 | 29 | Pnom0 = find(P_pvpost(m,:)>=Pmean_pre(1)*lmin & P_pvpost(m,:)<=Pmean_pre(1)*lmax & V_pvpost(m,:)>=Vmax_post); 30 | if size(Pnom0,2)>=3 31 | Pnom0 = find(P_pvpost(m,:)>=Pmean_pre(1)*0.99 & P_pvpost(m,:)<=Pmean_pre(1)*1.01 & V_pvpost(m,:)>=Vmax_post); 32 | end 33 | if size(Pnom0,2)==0 34 | Pnom0 = find(P_pvpost(m,:)>=Pmean_pre(1)*0.9 & P_pvpost(m,:)<=Pmean_pre(1)*1.1 & V_pvpost(m,:)>=Vmax_post); 35 | end 36 | absVal=abs(Pmean_pre(1)-P_pvpost(m,Pnom0)); 37 | minVal=min(abs(Pmean_pre(1)-P_pvpost(m,Pnom0))); 38 | selVal=find(absVal==minVal); 39 | Pnom_A=Pnom0(selVal); 40 | 41 | %% 42 | Pnom1 = find(P_pvpost(m,:)>=Pmean_pre(2)*lmin & P_pvpost(m,:)<=Pmean_pre(2)*lmax & V_pvpost(m,:)>=Vmax_post); 43 | if size(Pnom1,2)>=3 44 | Pnom1 = find(P_pvpost(m,:)>=Pmean_pre(2)*0.99 & P_pvpost(m,:)<=Pmean_pre(2)*1.01 & V_pvpost(m,:)>=Vmax_post); 45 | end 46 | if size(Pnom1,2)==0 47 | Pnom1 = find(P_pvpost(m,:)>=Pmean_pre(2)*0.9 & P_pvpost(m,:)<=Pmean_pre(2)*1.1 & V_pvpost(m,:)>=Vmax_post); 48 | end 49 | absVal1=abs(Pmean_pre(2)-P_pvpost(m,Pnom1)); 50 | minVal1=min(abs(Pmean_pre(2)-P_pvpost(m,Pnom1))); 51 | selVal1=find(absVal1==minVal1); 52 | Pnom_B=Pnom1(selVal1); 53 | 54 | %% 55 | 56 | if Pmax_post>= Pmean_pre(3) 57 | Pnom2 = find(P_pvpost(m,:)>=Pmean_pre(3)*lmin & P_pvpost(m,:)<=Pmean_pre(3)*lmax & V_pvpost(m,:)>=Vmax_post); 58 | if size(Pnom2,2)>=3 59 | Pnom2 = find(P_pvpost(m,:)>=Pmean_pre(3)*0.99 & P_pvpost(m,:)<=Pmean_pre(3)*1.01 & V_pvpost(m,:)>=Vmax_post); 60 | end 61 | if (size(Pnom2,2)==0 ) 62 | Pnom2 = find(P_pvpost(m,:)>=Pmean_pre(3)*0.9 & P_pvpost(m,:)<=Pmean_pre(3)*1.1 & V_pvpost(m,:)>=Vmax_post); 63 | end 64 | absVal2=abs(Pmean_pre(3)-P_pvpost(m,Pnom2)); 65 | minVal2=min(abs(Pmean_pre(3)-P_pvpost(m,Pnom2))); 66 | selVal2=find(absVal2==minVal2); 67 | Pnom_C=Pnom2(selVal2); 68 | 69 | PnomC= P_pvpost(m,Pnom_C) 70 | VnomC= V_pvpost(m,Pnom_C); 71 | 72 | else 73 | 74 | PnomC=Pmean_pre(3); 75 | VnomC=Vmax_post; 76 | end 77 | 78 | PnomA= P_pvpost(Pnom_A); 79 | VnomA= V_pvpost(Pnom_A); 80 | 81 | PnomB= P_pvpost(Pnom_B); 82 | VnomB= V_pvpost(Pnom_B); 83 | 84 | PnomX=[PnomA;PnomB;PnomC]; 85 | VnomX=[VnomA;VnomB;VnomC]; 86 | 87 | % Vlim_post1=(VnomA-Vlim_pre)/Vlim_pre; 88 | % Vlim_post2=(VnomB-Vlim_pre)/Vlim_pre; 89 | % Vlim_post3=(VnomC-Vlim_pre)/Vlim_pre; 90 | 91 | Vlim_post1=(VnomA-Vlim_post)/Vlim_post; 92 | Vlim_post2=(VnomB-Vlim_post)/Vlim_post; 93 | Vlim_post3=(VnomC-Vlim_post)/Vlim_post; 94 | 95 | Vlim_post0=[Vlim_post1;Vlim_post2;Vlim_post3] 96 | 97 | Plim_post1=(Plim_post-PnomA)/Plim_post; 98 | Plim_post2=(Plim_post-PnomB)/Plim_post; 99 | Plim_post3=(Plim_post-PnomC)/Plim_post; 100 | 101 | Plim_post0=[Plim_post1;Plim_post2;Plim_post3] 102 | %% 103 | 104 | SBI=[ PLimits_pre(1), PLimits_pre(2), PLimits_pre(3),VLimits_pre(1),VLimits_pre(2),VLimits_pre(3);... 105 | Plim_post0(1) , Plim_post0(2) , Plim_post0(3) ,Vlim_post0(1) ,Vlim_post0(2) ,Vlim_post0(3)] 106 | %% 107 | ABI=[min(SBI(:,1)),min(SBI(:,2)),min(SBI(:,3)),min(SBI(:,4)),min(SBI(:,5)),min(SBI(:,6))] 108 | 109 | GBI=[min(ABI(1:3)),min(ABI(4:6))] 110 | %% 111 | if kk==1 112 | if m==1 113 | ll=1; 114 | PP=1; 115 | end 116 | SBI1(ll:ll+1,:)=SBI; 117 | ABI1(PP,:)=ABI; 118 | GBI1(PP,:)=GBI; 119 | DataPre1(:,:,m).limits = [Plim_pre;Vlim_pre]; 120 | DataPre1(:,:,m).mean = [P0 P1 P2(kk);V0 V1 V2(kk)]; 121 | DataPre1(:,:,m).deltas = [PLimits_pre';VLimits_pre']; 122 | DataPre1(:,:,m).curve = [P_pvpre1',V_pvpre1']; 123 | DataPost1(:,:,m).limits = [Plim_post;Vlim_post]; 124 | DataPost1(:,:,m).mean = [PnomX';VnomX']; 125 | DataPost1(:,:,m).deltas = [Plim_post0';Vlim_post0']; 126 | DataPost1(:,:,m).curve = [P_pvpost',V_pvpost']; 127 | ll=ll+2; 128 | PP=PP+1; 129 | else 130 | if m==1 131 | hh=1; 132 | qq=1; 133 | end 134 | SBI2(hh:hh+1,:)=SBI; 135 | ABI2(qq,:)=ABI; 136 | GBI2(qq,:)=GBI; 137 | 138 | DataPre2(:,:,m).limits = [Plim_pre;Vlim_pre]; 139 | DataPre2(:,:,m).mean = [P0 P1 P2(kk);V0 V1 V2(kk)]; 140 | DataPre2(:,:,m).deltas = [PLimits_pre';VLimits_pre']; 141 | DataPre2(:,:,m).curve = [P_pvpre2',V_pvpre2']; 142 | DataPost2(:,:,m).limits = [Plim_post;Vlim_post]; 143 | DataPost2(:,:,m).mean = [PnomX';VnomX']; 144 | DataPost2(:,:,m).deltas = [Plim_post0';Vlim_post0']; 145 | DataPost2(:,:,m).curve = [P_pvpost',V_pvpost']; 146 | hh=hh+2; 147 | qq=qq+1; 148 | end 149 | end 150 | 151 | end 152 | 153 | end 154 | -------------------------------------------------------------------------------- /_source/v0_3_Nara/03_b_Voltage_Stability_Indexes_single_flow/verline.m: -------------------------------------------------------------------------------- 1 | function verline(x,linetype,label); 2 | 3 | g=ishold(gca); 4 | hold on 5 | y=get(gca,'ylim'); 6 | h=plot([x x],y,linetype); 7 | 8 | if exist('label') 9 | xx=get(gca,'xlim'); 10 | xrange=xx(2)-xx(1); 11 | xunit=(x-xx(1))/xrange; 12 | if xunit<0.8 13 | text(x+0.01*xrange,y(1)+0.1*(y(2)-y(1)),label,'color',get(h,'color')) 14 | else 15 | text(x-.05*xrange,y(1)+0.1*(y(2)-y(1)),label,'color',get(h,'color')) 16 | end 17 | end -------------------------------------------------------------------------------- /_source/v0_3_Nara/03_b_Voltage_Stability_Indexes_single_flow/vline.m: -------------------------------------------------------------------------------- 1 | function hhh=vline(x,in1,in2) 2 | % function h=vline(x, linetype, label) 3 | % 4 | % Draws a vertical line on the current axes at the location specified by 'x'. Optional arguments are 5 | % 'linetype' (default is 'r:') and 'label', which applies a text label to the graph near the line. The 6 | % label appears in the same color as the line. 7 | % 8 | % The line is held on the current axes, and after plotting the line, the function returns the axes to 9 | % its prior hold state. 10 | % 11 | % The HandleVisibility property of the line object is set to "off", so not only does it not appear on 12 | % legends, but it is not findable by using findobj. Specifying an output argument causes the function to 13 | % return a handle to the line, so it can be manipulated or deleted. Also, the HandleVisibility can be 14 | % overridden by setting the root's ShowHiddenHandles property to on. 15 | % 16 | % h = vline(42,'g','The Answer') 17 | % 18 | % returns a handle to a green vertical line on the current axes at x=42, and creates a text object on 19 | % the current axes, close to the line, which reads "The Answer". 20 | % 21 | % vline also supports vector inputs to draw multiple lines at once. For example, 22 | % 23 | % vline([4 8 12],{'g','r','b'},{'l1','lab2','LABELC'}) 24 | % 25 | % draws three lines with the appropriate labels and colors. 26 | % 27 | % By Brandon Kuczenski for Kensington Labs. 28 | % brandon_kuczenski@kensingtonlabs.com 29 | % 8 November 2001 30 | 31 | if length(x)>1 % vector input 32 | for I=1:length(x) 33 | switch nargin 34 | case 1 35 | linetype='r:'; 36 | label=''; 37 | case 2 38 | if ~iscell(in1) 39 | in1={in1}; 40 | end 41 | if I>length(in1) 42 | linetype=in1{end}; 43 | else 44 | linetype=in1{I}; 45 | end 46 | label=''; 47 | case 3 48 | if ~iscell(in1) 49 | in1={in1}; 50 | end 51 | if ~iscell(in2) 52 | in2={in2}; 53 | end 54 | if I>length(in1) 55 | linetype=in1{end}; 56 | else 57 | linetype=in1{I}; 58 | end 59 | if I>length(in2) 60 | label=in2{end}; 61 | else 62 | label=in2{I}; 63 | end 64 | end 65 | h(I)=vline(x(I),linetype,label); 66 | end 67 | else 68 | switch nargin 69 | case 1 70 | linetype='r:'; 71 | label=''; 72 | case 2 73 | linetype=in1; 74 | label=''; 75 | case 3 76 | linetype=in1; 77 | label=in2; 78 | end 79 | 80 | 81 | 82 | 83 | g=ishold(gca); 84 | hold on 85 | 86 | y=get(gca,'ylim'); 87 | h=plot([x x],y,linetype); 88 | if length(label) 89 | xx=get(gca,'xlim'); 90 | xrange=xx(2)-xx(1); 91 | xunit=(x-xx(1))/xrange; 92 | if xunit<0.8 93 | text(x+0.01*xrange,y(1)+0.1*(y(2)-y(1)),label,'color',get(h,'color')) 94 | else 95 | text(x-.05*xrange,y(1)+0.1*(y(2)-y(1)),label,'color',get(h,'color')) 96 | end 97 | end 98 | 99 | if g==0 100 | hold off 101 | end 102 | set(h,'tag','vline','handlevisibility','off') 103 | end % else 104 | 105 | if nargout 106 | hhh=h; 107 | end 108 | 109 | 110 | -------------------------------------------------------------------------------- /_source/v0_3_Nara/2015_WP$_New Indices_Presentation.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v0_3_Nara/2015_WP$_New Indices_Presentation.pptx -------------------------------------------------------------------------------- /_source/v1/01_Static_Overload/MatlabImplementation/Over_Load.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v1/01_Static_Overload/MatlabImplementation/Over_Load.mat -------------------------------------------------------------------------------- /_source/v1/01_Static_Overload/MatlabImplementation/Overload-1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v1/01_Static_Overload/MatlabImplementation/Overload-1.mat -------------------------------------------------------------------------------- /_source/v1/01_Static_Overload/MatlabImplementation/Overload-2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v1/01_Static_Overload/MatlabImplementation/Overload-2.mat -------------------------------------------------------------------------------- /_source/v1/01_Static_Overload/MatlabImplementation/Overload-3.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v1/01_Static_Overload/MatlabImplementation/Overload-3.mat -------------------------------------------------------------------------------- /_source/v1/01_Static_Overload/MatlabImplementation/static_overload.m: -------------------------------------------------------------------------------- 1 | 2 | function [Over_S,i2h,ridh,F,f,G,g,steady_state_lines]=static_overload(t,S1,p_1,dev0,deltime,simTime) 3 | %% Post-fault Over Load Index 4 | % This index is used to observe if the post-fault flows surpass the network capacity, 5 | % by monitoring the power flows through the transmission lines right after an outage occurs. 6 | % 7 | % 8 | % [Sindex]=static_overload(t,t1,Signal,w,p,d); 9 | % 10 | % INPUTS 11 | % t - Time vector 12 | % S - Apparent power flow 13 | % p - Exponent 14 | % d - Deviation allowed of power flow from nominal value, e.g. 10 for +10% 15 | % 16 | % OUTPUTS 17 | % Sindex -Overload index 18 | % 19 | % Version 1.2 20 | 21 | 22 | %% OVERLOAD 23 | pre0 = 5; 24 | post0 = 100; 25 | 26 | dev0 = dev0/100; 27 | nl = size(S1,2); 28 | wf_i = ones(1,nl); % Uniform weights in all Lines is assumed 29 | Snom = mean(S1(1:pre0,:)); % Nominal value (pre-contingency) 30 | Smax = Snom*(1+dev0); % Over power flow limits 31 | Spost = S1(end-post0:end,:); 32 | Smean = mean(Spost); 33 | 34 | % Remove lines out of service 35 | xxx=[];k=1; 36 | for i=1:nl 37 | if abs(Smean(1,i))<1e-2 38 | xxx(k,1)=i; 39 | S1(:,i)=0; 40 | Smean(1,i)=0; 41 | Snom(1,i)=0; 42 | k=k+1; 43 | end 44 | end 45 | clear k 46 | 47 | k=1; over_line=[]; 48 | for i=1:nl 49 | indxs_loc=(wf_i(i)*((abs(Smean(1,i))/abs(Smax(1,i)))^p_1)); 50 | index_red(i)=indxs_loc; 51 | 52 | 53 | if indxs_loc>=1 54 | indx(i)=indxs_loc; 55 | over_line(k)=i; % indices of lines violating limits 56 | k=k+1; 57 | else 58 | indx(i)=1; 59 | end 60 | 61 | 62 | rid(i,1) = index_red(i).^(1/p_1); 63 | if rid(i)<=1 64 | ridh(i,1)=1; 65 | i2h(i,1)=1; 66 | else 67 | ridh(i,1)= rid(i); 68 | i2h(i,1)=index_red(i); 69 | end 70 | 71 | end 72 | for i=1:size(rid) 73 | Fx(i)=rid(i); 74 | FFx(i)=i; 75 | end 76 | F=[FFx;Fx]; 77 | F=F'; 78 | Overloaded_lines=over_line'; 79 | for i=1:size(Overloaded_lines) 80 | fx(i)=ridh(Overloaded_lines(i)); 81 | ffx(i)=Overloaded_lines(i); 82 | end 83 | f=[ffx;fx]; 84 | f=f'; 85 | Over_S=sum(i2h)/nl; 86 | 87 | %% Plotting results (if required) 88 | % if Over_S>=1 89 | % nvl=size(over_line,2); %Number of lines violating the limits 90 | % Sextra_pu= indx(over_line)/max(indx(over_line)); 91 | % for i=1:nvl 92 | % if indx(over_line(i)).^(1/p_1)<=2 93 | % indx_over_per(i,1)=((indx(over_line(i)).^(1/p_1))-1)*100; 94 | % else 95 | % indx_over_per(i,1)=((indx(over_line(i)).^(1/p_1)))*100; 96 | % end 97 | % end 98 | % 99 | % if nvl>=1 100 | % 101 | % figure;bar(Smean(1,over_line),'g');hold on;bar(Smax(1,over_line),'y'); legend('S_{mean}','S_{max_{limit}}') 102 | % xlabel('Line Number');ylabel('MVA'); title(['Lines violating the limits=',num2str(nvl)]); 103 | % set(gca,'XTick',[1:nvl]) 104 | % set(gca,'XTickLabel',over_line) 105 | % 106 | % figure;bar(Sextra_pu,'r') 107 | % rr=find(indx==max(indx)); 108 | % title(['Line ',num2str(rr),' with maximum violation of ',num2str(max(indx_over_per)),'% more']) 109 | % set(gca,'XTick',[1:nvl]) 110 | % set(gca,'XTickLabel',over_line) 111 | % 112 | % figure;plot(t,S1(:,rr));axis tight;title(['Line number ', num2str(rr),' with maximum violation']) 113 | % hold on; plot(t(end-post0:end),S1(end-post0:end,rr),'linewidth',3) 114 | % hold on; horline(t,Smax(:,rr),'k:');hold on; horline(t,mean(Spost(:,rr)),'r') 115 | % xlabel('Time (sec)'); ylabel('MVA') 116 | % end 117 | % 118 | % end 119 | %% 120 | t1=simTime-3*deltime; 121 | t2=simTime-2*deltime; 122 | t3=simTime-deltime; 123 | t4=simTime; 124 | S=S1; 125 | lines=size(S); 126 | 127 | % Sampling three equal intervals towards the end of the simulation for 'k-th' line 128 | for k=1:lines(2) 129 | count1=0;count2=0;count3=0; 130 | for i=1:length(t) 131 | if(t(i)>t1 && t(i)<=t2) 132 | count1=count1+1; 133 | SS1(count1,k)=S(i,k); 134 | tt1(count1,k)=t(i); 135 | else if (t(i)>t2 && t(i)<=t3) 136 | count2=count2+1; 137 | SS2(count2,k)=S(i,k); 138 | tt2(count2,k)=t(i); 139 | else if (t(i)>t3 && t(i)<=t4) 140 | count3=count3+1; 141 | SS3(count3,k)=S(i,k); 142 | tt3(count3,k)=t(i); 143 | end 144 | end 145 | end 146 | end 147 | 148 | % Calculating the slopes of the intervals for 'k-th' line 149 | for i=2:count1 150 | Slope1(i-1,k)=(SS1(i,k)-SS1(i-1,k))/(tt1(i,k)-tt1(i-1,k)); 151 | if Slope1(i-1,k)== Inf || Slope1(i-1,k)==-Inf 152 | Slope1(i-1,k)=0; 153 | end 154 | end 155 | 156 | for i=2:count2 157 | Slope2(i-1,k)=(SS2(i,k)-SS2(i-1,k))/(tt2(i,k)-tt2(i-1,k)); 158 | if Slope2(i-1,k)== Inf || Slope2(i-1,k)==-Inf 159 | Slope2(i-1,k)=0; 160 | end 161 | end 162 | 163 | for i=2:count3 164 | Slope3(i-1,k)=(SS3(i,k)-SS3(i-1,k))/(tt3(i,k)-tt3(i-1,k)); 165 | end 166 | 167 | % Calculation of mean slope of the interval for 'k-th' line 168 | mean_slope(1,k)=mean(Slope1(:,k)); 169 | mean_slope(2,k)=mean(Slope2(:,k)); 170 | mean_slope(3,k)=mean(Slope3(:,k)); 171 | 172 | % Calculation of slope variation between the intervals for 'k-th' line 173 | slope_change1(k,1)=(mean_slope(2,k)-mean_slope(1,k)); 174 | slope_change1(k,2)=(mean_slope(3,k)-mean_slope(2,k)); 175 | 176 | % Calculation of the difference between the slope variation for 'k-th' line 177 | variation(k,1)=(abs(slope_change1(k,2)-slope_change1(k,1))); 178 | end 179 | 180 | % Assigning all the lines to an array 181 | for m=1:lines(2) 182 | mm(m,1)=m; 183 | end 184 | 185 | G=[mm variation]; % Matrix with slope variation of all lines 186 | 187 | c1=0; %counting variable 188 | % loop to find the lines in which the power change/variation is high 189 | for i=1:lines(2) 190 | if (variation(i)>2.5) 191 | c1=c1+1; 192 | GG(c1,1)=variation(i); 193 | gg(c1,1)=mm(i); 194 | end 195 | end 196 | % if all lines reaches steady state then setting g to zero 197 | if c1>0 198 | g=[gg,GG]; 199 | else 200 | g=[0,0]; 201 | end 202 | [mm slope_change1]; 203 | [mm variation]; 204 | % figure;plot(slope_change1(:,1),'-ob'); 205 | % hold on;plot(slope_change1(:,2),'-or'); 206 | % Finding the lines in which reached steady state 207 | Slines=0; % variable to count the lines which reached steady state 208 | for i=1:lines(2) 209 | if (slope_change1(i,1)>0 && slope_change1(i,2)<0 || abs(slope_change1(i,2))<=abs(slope_change1(i,1)) && variation(i,1)<0.01) 210 | Slines=Slines+1; 211 | steady_state_lines(Slines,1)=i; 212 | end 213 | end 214 | if Slines==0 215 | steady_state_lines=0; 216 | end 217 | 218 | end -------------------------------------------------------------------------------- /_source/v1/01_Static_Overload/MatlabImplementation/static_overload_index_testing.m: -------------------------------------------------------------------------------- 1 | clear all;clc;close all 2 | 3 | %% Load time series 4 | 5 | load Over_Load 6 | %load Overload-1 7 | %load Overload-2 8 | %load Overload-3 9 | %% POST-FAULT OVER LOADS 10 | 11 | t; % Time vector 12 | S = S1; % Input signal, Aparent power (S) size t x N 13 | p = 3; % Exponent used to magnify problems, value between 1 to "inf" 14 | d = 10; % Maximum Variation allowed from the nominal value (in %), e.g, 10 for 10% 15 | simTime=max(t);% Total simulation time of the given data 16 | Faultime=10; % Fault occuring time in the data 17 | deltime=10; %Time period of each sampled interval 18 | 19 | figure;plot(t,S); 20 | 21 | [f_x,i2h,ridh,F,f,G,g,steady_state_lines] = static_overload(t,S,p,d,deltime,simTime); 22 | 23 | f_x 24 | % outputs 25 | % f_x = Final index 26 | % F = Level of loading on each line 27 | % f = Overloaded lines 28 | % G = State of the lines 29 | % g = The lines in which the power flow variation are high 30 | %steady_state_lines= The lines which reached steady state 31 | %% eof -------------------------------------------------------------------------------- /_source/v1/01_Static_Overload/PythonImplementation/Python_code/requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v1/01_Static_Overload/PythonImplementation/Python_code/requirements.txt -------------------------------------------------------------------------------- /_source/v1/02_Static_UnderOver_Voltage/OverUnder_Voltage.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v1/02_Static_UnderOver_Voltage/OverUnder_Voltage.mat -------------------------------------------------------------------------------- /_source/v1/02_Static_UnderOver_Voltage/static_voltage.m: -------------------------------------------------------------------------------- 1 | function [V_index,i2h,ridh,Vol_violation,G,g,steady_state_bus]=static_voltage(t,BVm,p_2,dev,deltime,simTime) 2 | %% Post-fault Under/Over Voltage Index 3 | % Index for voltage of the transmission network right after an outage has occurred, 4 | % the index indicates if the voltage (V), surpass the limits of the operational standards 5 | % 6 | % 7 | % [Vindex]=satatic_voltage(t,V,p,d); 8 | % 9 | % INPUTS 10 | % t - Time vector 11 | % V - Voltages vector 12 | % p - Exponent 13 | % d - Deviation allowed of voltage from nominal value, e.g. 2 for +-2% 14 | % 15 | % OUTPUTS 16 | % Vindex -Under/Over voltage index 17 | % 18 | % 19 | % Version 1.1 20 | % 21 | 22 | dev=dev/100; 23 | 24 | 25 | %% The following parameters are used to calculate the index: 26 | pre0 = 5; 27 | post0 = 100; 28 | 29 | 30 | tpost = t(end-post0:end); % Period of time analyzed 31 | Vnom = mean(BVm(1:pre0,:)); % Nominal value (pre-contingency) 32 | Vpost = BVm(end-post0:end,:); % Voltage values post-contingency to be analyzed 33 | Vmin = Vnom*(1-dev); % Under voltage limits 34 | Vmax = Vnom*(1+dev); % Over voltage limits 35 | nb = size(Vnom,2); % Number of buses 36 | wv_i = ones(1,nb); % Uniform weights in all Buses 37 | 38 | 39 | delV = (Vmax - Vmin)/2; %Equation 40 | Vmean = mean(Vpost); %Equation 41 | 42 | 43 | % Remove bus out of service 44 | xxx=[];k=1; 45 | for i=1:nb 46 | if abs(Vmean(1,i))<1e-2 47 | xxx(k,1)=i; 48 | BVm(:,i)=0; 49 | Vmean(1,i)=0; 50 | Vnom(1,i)=0; 51 | Vmin(1,i)=0; 52 | Vmax(1,i)=0; 53 | wv_i(1,i)=0; 54 | k=k+1; 55 | end 56 | end 57 | clear k 58 | 59 | over_vol=0; 60 | %% Calculation of the actual index 61 | 62 | for i=1:nb 63 | 64 | 65 | % Index equation base on average value 66 | indxs =wv_i(1,i)*((abs(Vnom(i)-Vmean(:,i))./delV(i)).^p_2)'; 67 | 68 | 69 | % Applying considerations to understand the value of the index 70 | i2(i,1)=max(indxs); 71 | 72 | 73 | rid(i,1) = i2(i,1).^(1/p_2); 74 | 75 | if rid(i)<=1 76 | ridh(i,1)=1; 77 | i2h(i,1)=1; 78 | 79 | else if (rid(i)>=1) && (rid(i)<=5*(dev*100)) 80 | ridh(i,1)=rid(i); 81 | i2h(i,1)=i2(i); 82 | else 83 | ridh(i,1)= rid(i); 84 | i2h(i,1)=i2(i); 85 | end 86 | end 87 | 88 | if (rid(i)>1) && (rid(i)<5*(dev*100)) 89 | over_vol=over_vol+1; 90 | Vol_violation(over_vol,1)=i; 91 | end 92 | end 93 | 94 | 95 | % Buses with the voltage less/more than the aceptable min/max voltage 96 | 97 | 98 | if over_vol==0 99 | Vol_violation=0; 100 | end 101 | 102 | i2_tot=sum(i2); 103 | 104 | %%%%%%%%%%%% Under/Over Voltage Index %%%%%%%%%%% 105 | V_index = sum(i2h)/(nb); % The actual index normalized 106 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 107 | 108 | 109 | 110 | %% Ploting results 111 | % r1 = find(i2>=1); % index of lines violating limits 112 | % nvl= size(r1,1); % number of lines violating limits 113 | % r2 = (i2).^(1/p_2); 114 | % nvlsevere=0; 115 | % 116 | % if nvl>0 117 | % figure;plot(t,BVm(:,r1));axis tight 118 | % title(['Lines violating limits = ', num2str(nvl),' Index=',num2str(V_index)]) 119 | % xlabel('Time (sec)') 120 | % ylabel('Voltage') 121 | % if nvlsevere>0 122 | % figure;plot(t,BVm(:,r20));axis tight 123 | % title(['Lines (',num2str(nvlsevere), ') violating limits ',num2str(dev*100),' %']) 124 | % xlabel('Time (sec)') 125 | % ylabel('Voltage') 126 | % end 127 | % a= find(i2(r1)==max(i2(r1))); 128 | % mm=r1(1); 129 | % 130 | % figure;plot(t,BVm(:,mm));axis tight 131 | % hold on; plot(t(end-post0:end),BVm(end-post0:end,mm),'linewidth',3) 132 | % hold on; horline(t,Vmin(mm),'k:');horline(t,Vmax(mm),'k:') 133 | % hold on; horline(t,mean(Vpost(:,mm)),'r') 134 | % title(['Line ', num2str(mm),' with maximum violation, v=',num2str(V_index)]) 135 | % xlabel('Time (sec)') 136 | % ylabel('Voltage') 137 | % end 138 | 139 | %% 140 | clear k; 141 | tt1=simTime-3*deltime;tt2=simTime-2*deltime;tt3=simTime-deltime;tt4=simTime; 142 | V=BVm; 143 | for k=1:nb 144 | count1=0;count2=0;count3=0; 145 | for i=1:length(t) 146 | if(t(i,1)>tt1 && t(i,1)<=tt2) 147 | count1=count1+1; 148 | V1(count1,k)=V(i,k); 149 | t1(count1,k)=t(i,1); 150 | else if (t(i,1)>tt2 && t(i,1)<=tt3) 151 | count2=count2+1; 152 | V2(count2,k)=V(i,k); 153 | t2(count2,k)=t(i,1); 154 | else if (t(i,1)>tt3 && t(i,1)<=tt4) 155 | count3=count3+1; 156 | V3(count3,k)=V(i,k); 157 | t3(count3,k)=t(i); 158 | end 159 | end 160 | end 161 | end 162 | % Calculating the slopes of the intervals for 'k-th' bus 163 | for i=2:count1 164 | Slope1(i-1,k)=(V1(i,k)-V1(i-1,k))/(t1(i,k)-t1(i-1,k)); 165 | if Slope1(i-1,k)== Inf || Slope1(i-1,k)==-Inf 166 | Slope1(i-1,k)=0; 167 | end 168 | end 169 | 170 | for i=2:count2 171 | Slope2(i-1,k)=(V2(i,k)-V2(i-1,k))/(t2(i,k)-t2(i-1,k)); 172 | if Slope2(i-1,k)== Inf || Slope2(i-1,k)==-Inf 173 | Slope2(i-1,k)=0; 174 | end 175 | end 176 | 177 | for i=2:count3 178 | Slope3(i-1,k)=(V3(i,k)-V3(i-1,k))/(t3(i,k)-t3(i-1,k)); 179 | if Slope3(i-1,k)== Inf || Slope3(i-1,k)==-Inf 180 | Slope3(i-1,k)=0; 181 | end 182 | end 183 | 184 | % Calculation of mean slope of the interval for 'k-th' bus 185 | mean_slope(1,k)=mean(Slope1(:,k)); 186 | mean_slope(2,k)=mean(Slope2(:,k)); 187 | mean_slope(3,k)=mean(Slope3(:,k)); 188 | 189 | % Calculation of slope variation between the intervals for 'k-th' bus 190 | slope_change1(k,1)=(mean_slope(2,k)-mean_slope(1,k)); 191 | slope_change1(k,2)=(mean_slope(3,k)-mean_slope(2,k)); 192 | 193 | % Calculation of the difference between the slope variation for 'k-th' bus 194 | variation(k,1)=(abs(slope_change1(k,2)-slope_change1(k,1))); 195 | end 196 | % Assigning all the buses to an array 197 | for m=1:nb 198 | buses(m,1)=m; 199 | end 200 | 201 | G=[buses variation]; % Matrix with slope variation of bus voltages 202 | 203 | % loop to find the lines in which the voltage variation is high 204 | c1=0; %counting variable 205 | for i=1:nb 206 | if (variation(i)>1) 207 | c1=c1+1; 208 | GG(c1,1)=variation(i); 209 | gg(c1,1)=buses(i); 210 | end 211 | end 212 | 213 | 214 | % if all voltages reaches steady state then setting g to zero 215 | if c1>0 216 | g=[gg,GG]; 217 | else 218 | g=[0,0]; 219 | end 220 | 221 | % Finding the lines in which reached steady state 222 | SS_bus=0; % variable to count the lines which reached steady state 223 | for i=1:nb 224 | if ( variation(i,1)<=0.001) 225 | SS_bus=SS_bus+1; 226 | steady_state_bus(SS_bus,1)=i; 227 | end 228 | 229 | end 230 | 231 | 232 | 233 | end % function end 234 | 235 | 236 | -------------------------------------------------------------------------------- /_source/v1/02_Static_UnderOver_Voltage/static_voltage_index_testing.m: -------------------------------------------------------------------------------- 1 | % POST-FAULT UNDER/OVER VOLTAGE 2 | 3 | % Sample script 4 | clear all;clc;close all 5 | 6 | %% Load time series 7 | load OverUnder_Voltage 8 | 9 | % POST-FAULT UNDER/OVER VOLTAGE 10 | %% Input data and options into the index 11 | t; % time vector 12 | V = BVm; % Voltage magnitudes - Matrix of size t x N 13 | p = 3; % Exponent used to scale the index, value between 1 to "inf" 14 | d = 1; % Maximum voltage variation allowed (in %) of the nominal value, i.e. 2 for 2% 15 | simTime=max(t); % Total simulation time of the given data 16 | deltime=25; %Time period of each interval 17 | 18 | 19 | % Compute the index 20 | [v_x,i2h,F,f,G,g,Steady_State_buses] = static_voltage(t,V,p,d,deltime,simTime); 21 | 22 | % Display the index in the Command Window 23 | v_x 24 | %% 25 | plot(t,V); 26 | if SS_buses~=0 27 | figure;plot(t,V(:,SS_buses(:,:))) 28 | end 29 | % outputs 30 | % v_x = Final index 31 | % F = voltage level of each bus as per the index calculation 32 | % f = Bus numbers which violated voltage limits 33 | % Steady_State_buses = Bus numbers whose voltages reached steady state 34 | % G = Rate of change of voltage variation of all buses 35 | % g = Buses in high voltage variation 36 | %% eof -------------------------------------------------------------------------------- /_source/v1/03_Dynamic Transient/Gentrip_1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v1/03_Dynamic Transient/Gentrip_1.mat -------------------------------------------------------------------------------- /_source/v1/03_Dynamic Transient/Gentrip_2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v1/03_Dynamic Transient/Gentrip_2.mat -------------------------------------------------------------------------------- /_source/v1/03_Dynamic Transient/Gentrip_3.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v1/03_Dynamic Transient/Gentrip_3.mat -------------------------------------------------------------------------------- /_source/v1/03_Dynamic Transient/Gentrip_4.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v1/03_Dynamic Transient/Gentrip_4.mat -------------------------------------------------------------------------------- /_source/v1/03_Dynamic Transient/dynamic_transcient_index_testing.m: -------------------------------------------------------------------------------- 1 | clear all;clc;close all 2 | 3 | %% Load time series 4 | 5 | load Transient 6 | 7 | %% TRANSIENT STABILITY 8 | 9 | t; % Time vector size t x 1 10 | delta; % Angle of the machines size t x N; 11 | M; % Two time interia (H) of the machines (M=2*H), size 1 x N 12 | 13 | [J]=dynamic_transient(t,delta,M) 14 | 15 | 16 | % outputs 17 | % J = Final index 18 | 19 | 20 | -------------------------------------------------------------------------------- /_source/v1/03_Dynamic Transient/dynamic_transient.m: -------------------------------------------------------------------------------- 1 | function [J,delta_N,xxx]=dynamic_transient(t,delta,M) 2 | %% Integral Square Generator Angle (ISGA) index. 3 | % Used to evaluate the transient stability of the system, simple approach that looks at the integral 4 | % of the square of the angular deviation from equilibrium (COI). 5 | % 6 | % J =dynamic_transient(t,delta,M) 7 | % 8 | % INPUTS 9 | % t - Time vector 10 | % delta - Machine angles vector 11 | % M - Mechanical Starting time, two time interia (H) of the machines (M=2*H) 12 | % 13 | % OUTPUTS 14 | % J - Transien stability index 15 | % 16 | % Version 1.2 17 | % 18 | 19 | 20 | if size(M,2)>1 21 | M=M'; 22 | end 23 | 24 | 25 | %% 26 | nm=size(delta,2); % machines number 27 | nt = size(t,1); % simulation length 28 | 29 | post0 = 100; 30 | delta_post = delta(end-post0:end,:); 31 | delta_mean = mean(delta_post); 32 | 33 | % Remove generators out of service 34 | xxx=[];k=1; 35 | for i=1:nm 36 | if delta_mean(1,i)<-1e20 37 | xxx(k,1)=i; 38 | delta(:,i)=0; 39 | delta_mean(1,i)=0; 40 | M(i)=0; 41 | k=k+1; 42 | end 43 | end 44 | clear k 45 | delta_N=delta; 46 | 47 | 48 | 49 | for i=1:nm 50 | SM(:,i)=M(i)*delta(:,i); 51 | end 52 | 53 | num_coa = sum(SM,2); 54 | den_coa = sum(M); 55 | delta_coa = num_coa/den_coa; 56 | 57 | for i=1:nm 58 | Jg(:,i)=M(i)*(delta(:,i)-delta_coa).^2; 59 | Jcoa(:,i)=trapz(t,Jg(:,i)); 60 | end 61 | 62 | 63 | Mtot = sum(M); 64 | T = nt; 65 | Jtot = sum(Jcoa); 66 | MT = 1/(Mtot*T); 67 | J1 = MT*Jtot; 68 | 69 | J=J1/nm; 70 | 71 | -------------------------------------------------------------------------------- /_source/v1/03_Dynamic Transient/transient.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v1/03_Dynamic Transient/transient.mat -------------------------------------------------------------------------------- /_source/v1/04_a_ Dynamic Small_Signal_prony_ERA/SmallSignal.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v1/04_a_ Dynamic Small_Signal_prony_ERA/SmallSignal.mat -------------------------------------------------------------------------------- /_source/v1/04_a_ Dynamic Small_Signal_prony_ERA/dynamic_smallsignal_testing.m: -------------------------------------------------------------------------------- 1 | clear all;clc;close all 2 | 3 | %% Load time series 4 | % 5 | load SmallSignal 6 | 7 | 8 | 9 | %% ERA & PRONY 10 | 11 | Method =2; % Method=1 (ERA analysis) 12 | % Method=2 (PRONY analysis recommended) 13 | 14 | t; % Time Vector 15 | SigAn = LP1; % Signals to analyze (Active power flows at critical lines) 16 | 17 | t1=[1,35,25]; % Select window section t1(1)= Initial Time 18 | % t1(2)= Final time 19 | % t1(3)= From where to start ERA 20 | Pcent=100; % Amount of signals to be considered, 100=100% for all signals, 21 | f=[0.1,1]; % Range of frequencies to analyze damping of modes f(1)=fmin, f(2)=fmax both in Hz 22 | Nmodes=[]; % Number of Modes to estimate on each approach, Nmodes=[]; automatic selection, Nmodes=[2]; force Algorithm to choose 2 modes. 23 | Damp=[0,5,10]; % Damping ratios, Calculate damping distance from each mode to the specified dampings, ie [0%, 5%, 10%] 24 | flag1=1; % if 1 show plots 25 | 26 | [GMI,AMI,SMI,Poles,Freq,Ener]=smallsignal(Method,t,SigAn,t1,Pcent,f,Nmodes,Damp,flag1); 27 | 28 | SMI 29 | AMI 30 | GMI 31 | 32 | %Outputs 33 | % 34 | % Ener Results of sorting signals "SigAn" according to energy 35 | % Ener.y Sorted signals from t1(1) to t1(2) 36 | % Ener.yh Sorted signals from t1(3) to t1(2) 37 | % Ener.t Time vector from t1(1) to t1(2) 38 | % Ener.th Time vector from t1(2) to t1(2) 39 | % 40 | % Freq Frequencies found from the FFT filter 41 | % 42 | % Poles Output of applying ERA or PRONY to set of signals "Ener.yh" 43 | % 44 | % if ERA 45 | % Poles.sys Estimated continous state-space model 46 | % 47 | % if PRONY 48 | % Poles.sys Estimated "A" matrix with modes identified 49 | % 50 | % SMI Single Mode Indicator, Matrix. 51 | % AMI All Mode Indicator, Vector. 52 | % GMI Global Mode Indicator, Gain. 53 | 54 | -------------------------------------------------------------------------------- /_source/v1/04_a_ Dynamic Small_Signal_prony_ERA/energy_sort.m: -------------------------------------------------------------------------------- 1 | function [ymm,tss,ymm_sec,tsec]=energy_sort(t,t1,BVm,Pcent,flag1) 2 | % 3 | % [ymm,ymm_sec,tsec]=energy_sort(t,t1,Signals,Energy%,flag1) 4 | % 5 | % 6 | % 7 | % 8 | 9 | %% Pre-processing the signals: Define the window of time to be analyzed 10 | 11 | % t1 =[tnom, tend, dt] with the following information: 12 | % 13 | % tnom -> Initial time to be analized (sec) 14 | % tend -> End time to be analized (sec) 15 | % dt ->Time to start analyzing small-signal 16 | 17 | 18 | % The following section extracts from the time vector "t", 19 | % the approximated values of "tnom" and "tend" defined in t1 20 | 21 | tnom0 = find(t>=t1(1)*0.95 & t<=t1(1)*1.05 ); 22 | if size(tnom0,1)>=3 23 | tnom0 = find(t>=t1(1)*0.999 & t<=t1(1)*1.001 ); 24 | end 25 | if size(tnom0,1)==0 26 | tnom0 = find(t>=t1(1)*0.9 & t<=t1(1)*1.1 ); 27 | end 28 | 29 | tend0 = find(t>=t1(2)*0.95 & t<=t1(2)*1.05); 30 | if size(tend0,1)>=3 31 | tend0 = find(t>=t1(2)*0.999 & t<=t1(2)*1.001 ); 32 | end 33 | if size(tend0,1)==0 34 | tend0 = find(t>=t1(2)*0.9 & t<=t1(2)*1.1 ); 35 | end 36 | 37 | tnom = tnom0(1); 38 | tend = tend0(end); 39 | tdel = t(tnom:tend); 40 | %dt = t1(3); 41 | 42 | 43 | 44 | %% Selecting voltage magnitudes with largest oscillation content 45 | nb = size(BVm,2); 46 | tss = t(tnom:1:tend); % Time window to analyze 47 | tdss = [tnom:1:tend]; % 48 | y_invest = BVm(tdss,:); % Voltage magnitudes using selected interval 49 | 50 | 51 | tosc0 = find(tss>=t1(3)*0.95 & tss<=t1(3)*1.05); 52 | if size(tosc0,1)>=3 53 | tosc0 = find(tss>=t1(3)*0.999 & tss<=t1(3)*1.001 ); 54 | end 55 | if size(tosc0,1)==0 56 | tosc0 = find(tss>=t1(3)*0.9 & tss<=t1(3)*1.1 ); 57 | end 58 | dt=tosc0(end); 59 | 60 | % Calculating the Energy of the signals 61 | for i=1:nb 62 | yme(:,i)=y_invest(:,i)-mean(y_invest(:,i)); % Detrended signals 63 | %ydtr(:,i)=dtrend(y_invest(:,i)); % Detrended using matlab function 64 | En_sigs(i)=sqrt(sum(abs(yme(:,i).^2))); % Energy 65 | end 66 | 67 | 68 | [Ener,Ind] = sort(En_sigs','descend'); % Sort energy from largest to smallest 69 | 70 | Pcent=100-Pcent; 71 | Emax=max(Ener); 72 | Emin=(max(Ener)*Pcent)/100; 73 | 74 | kk=1; 75 | for i=1:nb 76 | if Ener(i)>= Emin 77 | EnerM(kk,1)=Ener(i); 78 | IndM(kk,1)=Ind(i); 79 | kk=kk+1; 80 | end 81 | end 82 | 83 | y_dtrend=yme(:,IndM); 84 | ymm=y_dtrend; 85 | % ymm_sec=ymm((end-dt:end),:); 86 | % tsec=tss(end-dt:end); 87 | %ymm_sec=ymm((dt:end),:); 88 | ymm_sec=dtrend(ymm((dt:end),:)); 89 | tsec=tss(dt:end); 90 | 91 | 92 | 93 | 94 | % y_dtrend=yme(:,Ind(1:end)); 95 | % ymm=y_dtrend; 96 | % ymm_sec=ymm((end-dt:end),:); 97 | % tsec=tss(end-dt:end); 98 | 99 | % keyboard 100 | 101 | %% 102 | 103 | if flag1==1 104 | %figure;plot(tss,BVm(tdss,Ind(1:end)));axis tight % Plot the most significant signals 105 | figure;plot(tss,ymm);axis tight % Plot the most significant signals detrended 106 | title(['Signals sorted according to Enery, more than ',num2str(Pcent),' %']) 107 | %figure;plot(tss(end-dt:end,1),ymm(end-dt:end,:));axis tight 108 | figure;plot(tss(dt:end,1),ymm_sec);axis tight 109 | title(['Selected Window to analyze: ',num2str(dt),' samplings before ', num2str(t(tend)),' sec']) 110 | end -------------------------------------------------------------------------------- /_source/v1/04_a_ Dynamic Small_Signal_prony_ERA/fft_get.m: -------------------------------------------------------------------------------- 1 | function [fsend,magsend]=fft_get(t,x,alpha,flag1); 2 | 3 | t=t'; 4 | x=x'; 5 | 6 | n=size(t,2); % Number of points 7 | 8 | if mod(n,2) == 0 9 | n=n; 10 | else 11 | n=n-1; 12 | end 13 | 14 | 15 | 16 | %% Applying FFT to signal "x" and plotting real and imaginary part 17 | spectrum=fft(x); 18 | 19 | 20 | %keyboard 21 | 22 | %% 23 | %Verifying that first and middle components are real 24 | DCfisrst=spectrum(1:2); 25 | indNyq=n/2+1; 26 | NyquistMiddle=spectrum(indNyq-2:indNyq+2); 27 | 28 | 29 | %Fold the spectrum as algorithtm in Figure 12 of document 30 | spectrum = spectrum(1:indNyq); % truncate 31 | spectrum = spectrum/n; % scale 32 | spectrum(2:end) = 2*spectrum(2:end); % compensate for truncating negative freqs 33 | magnitude = abs(spectrum); % abs of complex numbers 34 | 35 | dt = t(3)-t(2); 36 | df = (1/dt)/n; % frequency resolution 37 | 38 | freqAx=[0:indNyq-1]'*df; % values of frequency axis 39 | 40 | [gains,indxs]=sort(magnitude','descend'); 41 | gains_norm=gains/gains(1); 42 | kk=find(gains_norm>=alpha); 43 | mm=size(kk,1); 44 | 45 | gsend=indxs(1:mm); 46 | fsend= freqAx(gsend); 47 | magsend=magnitude(gsend)'; 48 | 49 | %keyboard 50 | %% Various Plots 51 | mm=exist('flag1'); 52 | 53 | if mm 54 | 55 | 56 | % Plotting signal "x" and its first 20 points 57 | % figure 58 | % subplot(2,1,1) 59 | % plot(t,x);axis tight;grid on 60 | % ylabel('Units') 61 | % xlabel('Time[s]') 62 | % title('Signal') 63 | % subplot(2,1,2) 64 | % plot(t(1:20),x(1:20),'-o');axis tight;grid on 65 | % ylabel('Units') 66 | % xlabel('Time[s]') 67 | 68 | % figure 69 | % subplot(2,1,1) 70 | % plot(real(spectrum));axis tight;grid on 71 | % ylabel('Real') 72 | % title('Raw FFT spectrum') 73 | % subplot(2,1,2) 74 | % plot(imag(spectrum));axis tight;grid on 75 | % ylabel('Imaginary') 76 | % xlabel('Index number') 77 | 78 | figure 79 | plot(freqAx,magnitude);axis tight;grid on 80 | xlabel('Frequency[Hz]') 81 | ylabel('Magnitude[units]') 82 | [magMax,indMax]=max(magnitude); 83 | freqMax=freqAx(indMax); 84 | title(sprintf('Max magnitude=%f @ %fHz, \\Deltaf=%fHz',magMax,freqMax,df)) 85 | 86 | 87 | 88 | % figure 89 | % handlestem=stem(freqAx,magnitude); 90 | % set(handlestem(1),'Marker','none');grid on 91 | % xlabel('Frequency [Hz]') 92 | % ylabel('Magnitude [Hz]') 93 | % title(sprintf('Max magnitude=%f @ %fHz, \\Deltaf=%fHz',magMax,freqMax,df)) 94 | % 95 | % figure 96 | % fmax=find(freqAx==freqMax); 97 | % handlestem=stem(freqAx,magnitude); 98 | % axis([freqAx(fmax-5) freqAx(fmax+5) 0 max(magnitude)]) 99 | % set(handlestem(1),'Marker','none');grid on 100 | % xlabel('Frequency [Hz]') 101 | % ylabel('Magnitude [Hz]') 102 | % title(sprintf('Max magnitude=%f @ %fHz, \\Deltaf=%fHz',magMax,freqMax,df)) 103 | 104 | end -------------------------------------------------------------------------------- /_source/v1/04_a_ Dynamic Small_Signal_prony_ERA/pronyiTesla.m: -------------------------------------------------------------------------------- 1 | function [lamda,model]=pronyiTesla(t,y,XX,tstart,tend,T,shift,tstplot,tedplot,plotFlag); 2 | %[model]=pronyanalysis(t,y,n,tstart,tend,T,shift,tstplot,tedplot,plotFlag); 3 | %Prony analysis program for fitting to a ringdown 4 | % Inputs: 5 | % t = time vector (does not need to be equally spaced) -- column vector 6 | % t(1) is assumed to be 0; if not, all time variables are shifted by t(1). 7 | % y = ringdown matrix of order N by NChan corresponding to t, each column is a different signal 8 | % n = order of the estimated model 9 | % tstart = row vector of order 1 by NChan. tstart(k) is the starting 10 | % time for analysis for y(:,k). 11 | % tend = ending times for analysis (same dimension as tstart) 12 | % shift = flag; if shift = 1, residues are shifted to t = 0. 13 | % If the data is noisy, reccomend shift = 0. 14 | % T = sample period for analysis 15 | % tsttplot = starting time for model simulation 16 | % tedplot = ending time for model simulation 17 | % plotFlag = if = 1, plot results 18 | % Outputs (structured array): 19 | % model.Poles = ringdown pole matrix -- column k is for column k of y 20 | % model.Res = ringdown residue matrix 21 | % model.K = ringdown offset row vector 22 | % model.yhat = model signal matrix 23 | % model.that = time vector for yhat (starts at tstart) 24 | % 25 | % NOTE: It is reccomended that the N/(1+NChan) < 200, where 26 | % N = total number of data points in y to be analyzed, and 27 | % NChan = number of columns in y. 28 | 29 | 30 | % 1.0 Setup 31 | 32 | %Basic error checks 33 | 34 | if (size(y,2)~=size(tstart,2))|(size(y,2)~=size(tend,2)); error('Dimension error in y, tstart, tend'); end; 35 | if (size(tstart,1)~=1)|(size(tend,1)~=1); error('Dimension error in tstart or tend'); end; 36 | if (T<=0)|(tstplot>=tedplot)|(max(t)min(tstart')); error('data error'); end; 37 | if (size(t,1) ~= size(y,1))|(size(t,2)~=1); error('Dimension error in y or t'); end; 38 | 39 | %Data parameters 40 | NChannels = size(y,2); 41 | 42 | %Shift time parameters 43 | tstart = tstart-t(1); 44 | tend = tend-t(1); 45 | tstplot = tstplot-t(1); 46 | tedplot = tedplot-t(1); 47 | t = t-t(1); 48 | 49 | %Set up analysis data and calculate offset 50 | tanalysis = T*[0:1:ceil(max(tend')/T)+1]'; 51 | Nstart = zeros(1,NChannels); 52 | Nend = zeros(1,NChannels); 53 | yanal = zeros(length(tanalysis),NChannels); 54 | K = zeros(1,NChannels); 55 | for k=1:NChannels 56 | Nstart(k) = floor(tstart(k)/T)+1; 57 | Nend(k) = ceil(tend(k)/T)+1; 58 | yanal(:,k) = spline(t,y(:,k),tanalysis); 59 | K(1,k) = mean(yanal(Nstart(k):Nend(k),k)); 60 | yanal(:,k) = yanal(:,k)-K(k); 61 | end 62 | clear k 63 | 64 | %Find model order 65 | NdataPoints = Nend-Nstart+1; %Number of data points used for analysis on each channel 66 | Ntotal = sum(NdataPoints'); %Total number of data points used for Prony analysis 67 | %nOrder = round(Ntotal/(1+NChannels))-10; %Order of Linear Prediction 68 | nOrder=XX; 69 | %if (nOrder>50); nOrder=50; end; %Limit order to avoid numerical problems 70 | 71 | % 2.0 Solve Linear Prediction 72 | 73 | %Build matrix and vector 74 | for k=1:NChannels 75 | Ym = zeros(NdataPoints(k)-nOrder,nOrder); 76 | for kk=1:nOrder 77 | Ym(:,kk) = yanal(Nstart(k)+nOrder-kk:Nstart(k)-kk+NdataPoints(k)-1,k); 78 | end 79 | yv = yanal(Nstart(k)+nOrder:Nstart(k)+NdataPoints(k)-1,k); 80 | if k==1; 81 | Ymatrix = Ym; 82 | yvector = yv; 83 | else 84 | Ymatrix = [Ymatrix;Ym]; %Cancatinate the channels 85 | yvector = [yvector;yv]; 86 | end 87 | end 88 | clear Ym yv k kk 89 | % acoef = pinv(Ymatrix)*yvector; %characteristic eqn. Pseudo inverse using SVD 90 | acoef = Ymatrix\yvector; %This provides a much more accurate solution than the above line 91 | 92 | %Find poles 93 | zPoles = roots([1;-acoef]); 94 | sPoles = log(zPoles)/T; 95 | 96 | 97 | 98 | % 3.0 Solve for residues 99 | Res = zeros(nOrder,NChannels); 100 | for k=1:NChannels 101 | ZMatrix = zeros(NdataPoints(k),nOrder); 102 | for kk=1:NdataPoints(k) 103 | ZMatrix(kk,:) = (zPoles.').^(kk-1); 104 | end 105 | Res(:,k) = ZMatrix\yanal(Nstart(k):Nend(k),k); 106 | if shift==1; 107 | Res(:,k) = Res(:,k).*(zPoles.^(-Nstart(k)+1)); %Shift residues to time 0 108 | end 109 | end 110 | clear k kk 111 | 112 | % 4.0 Re-order using energy 113 | P = zeros(nOrder,NChannels); 114 | R = zeros(size(Res)); 115 | for k=1:NChannels 116 | clear E 117 | for kk=1:nOrder 118 | if abs(real(sPoles(kk)))<1e-8 119 | E(kk)=Res(kk,k)^2*(tend(k)-tstart(k)); 120 | else 121 | E(kk)=(Res(kk,k)^2/(2*real(sPoles(kk))))*(exp(2*real(sPoles(kk))*(tend(k)-tstart(k)))-1); 122 | end 123 | end 124 | E=E(:); 125 | [x,ii]=sort(E); 126 | R(:,k)=Res(ii,k); 127 | P(:,k)=sPoles(ii); 128 | M=[length(ii):-1:1]'; 129 | R(:,k)=R(M,k); 130 | P(:,k)=P(M,k); 131 | end 132 | clear M k x ii E 133 | 134 | %Simulate; 135 | that = [tstplot:T:tedplot]'; 136 | yhat = zeros(length(that),NChannels); 137 | for k=1:NChannels 138 | yhat(:,k) = K(k).*ones(size(that)); 139 | for kk=1:length(that); 140 | for n=1:nOrder; 141 | yhat(kk,k) = yhat(kk,k) + R(n,k)*exp(P(n,k)*that(kk)); 142 | end 143 | end; 144 | end; 145 | yhat=real(yhat); 146 | 147 | % 5.0 Place output in structured array 148 | model.Poles = P; 149 | model.Res = R; 150 | model.K = K; 151 | model.that = that; 152 | model.yhat = yhat; 153 | 154 | lamda=sPoles; 155 | 156 | 157 | 158 | % 6.0 Plot results 159 | if plotFlag==1 160 | figure 161 | hold on 162 | h1 = plot(t,y); 163 | h2 = plot(that,yhat,'--*');axis tight 164 | hold off 165 | xlabel('Time (sec)') 166 | %legend('Actual','Prony') 167 | end 168 | 169 | %Original plots 170 | % if plotFlag==1 171 | % for k=1:size(yhat,2) 172 | % figure 173 | % n = find(t(t>=tstplot&t<=tedplot)); 174 | % hold on 175 | % h1 = plot(t(n),y(n,k),'k','linewidth',1.5); 176 | % h2 = plot(that,yhat(:,k),'r--','linewidth',1.5); 177 | % hold off 178 | % xlabel('Time (sec)') 179 | % legend('Actual','Prony') 180 | % end 181 | % end -------------------------------------------------------------------------------- /_source/v1/04_a_ Dynamic Small_Signal_prony_ERA/smallsignal.m: -------------------------------------------------------------------------------- 1 | function [GMI_m,AMI_m,SMI,Poles,Frequencies,Ener]=smallsignal(flagMethod,t,SigAn,t1,Pcent,f,Nf,Damp,flag1); 2 | 3 | 4 | %% Sorting signals according to energy 5 | 6 | nsig = size(SigAn,2); % number of signals 7 | [ys,tss,ysec,tsec]=energy_sort(t,t1,SigAn,Pcent,flag1); 8 | 9 | nsec = size(ysec,2); % number of signals 10 | 11 | if nsec>=100 12 | y=ysec(:,1:100); 13 | else 14 | y=ysec; 15 | end 16 | 17 | Ener.y=ys; 18 | Ener.yh=ysec; 19 | Ener.t=tss; 20 | Ener.th=tsec; 21 | 22 | %keyboard 23 | 24 | %% Applying ideal filter (FFT) to signals with largest oscillation content 25 | 26 | nsig2 = size(y,2); %Number of signals 27 | fmin=f(1); %Minimum frequency Hz 28 | fmax=f(2); %Max requency Hz 29 | 30 | 31 | r=1; 32 | for i=1:nsig2 33 | [f_k,gain_k,]=fft_get(tsec,y(:,i),0.6); 34 | 35 | nfq = size(f_k,1); 36 | q = r+nfq-1; 37 | fqs(r:q,1) = f_k; 38 | fgains(r:q,1)=gain_k; 39 | fidx(i,1) = nfq; 40 | new = size(fqs,1); 41 | r = new+1; 42 | end 43 | 44 | Fred_find = fqs; 45 | nFreq=sum(fidx); 46 | clear fqs 47 | 48 | nsig; % Number of signals analyzed 49 | Fred_find; % Frequencies bwtween w1 and w2 within the set of signals 50 | fidx; % Number of frequencies found on each signal 51 | 52 | fss=unique(Fred_find); 53 | Frequencies = fss(find(fss~=0)); 54 | 55 | 56 | %% ERA 57 | if flagMethod==1 58 | 59 | if isempty(Nf) 60 | Nf=size(Frequencies,1); 61 | end 62 | 63 | 64 | 65 | nsig_y=size(y,2); 66 | fr = Nf; 67 | n=2*fr+2; %number of singular values to evaluate 68 | T = t(10)-t(9); 69 | [sysd,sv,mc] = eraiTesla(y,nsig_y,n,T,flag1); 70 | 71 | Poles.sys=sysd; 72 | Poles.sv=sv; 73 | Poles.mc=mc; 74 | 75 | nM = size(sysd.a,1); 76 | [Aq] = eig(sysd.a); 77 | fqmodes = Aq; 78 | ffreqq = abs(imag(fqmodes))/2/pi; 79 | fnfreqq = abs(fqmodes); 80 | fdampq = -cos(atan2(imag(fqmodes),real(fqmodes))); 81 | end 82 | 83 | %% Prony 84 | 85 | if flagMethod==2 86 | 87 | if isempty(Nf) 88 | Nf=size(Frequencies,1); 89 | end 90 | 91 | fr = Nf; % Number of modes 92 | t0 = tsec; % time vector of order 1xt 93 | yr = y; % ringdown matrix of order txNsig, each column is a different signal 94 | Nsig = size(yr,2); % number of signals or channels 95 | n=2*fr+2; %number of singular values to evaluate 96 | 97 | tstart = tsec(1)*ones(1,Nsig); %starting time for analysis 98 | tend = tsec(end)*ones(1,Nsig);%ending times for analysis 99 | T = tsec(end)-tsec(end-1); %sample period for analysis 100 | flag0 = 1; %if flag1 = 1, residues are shifted to t = 0. 101 | tstplot= tsec(1); %starting time for model simulation 102 | tedplot= tsec(end); %ending time for model simulation 103 | flagN = flag1; %if flag2=1, plot results 104 | 105 | [lamda,modelb]=pronyiTesla(t0,yr,n,tstart,tend,T,flag0,tstplot,tsec(end),flagN); 106 | 107 | Poles.sys=diag(lamda); 108 | 109 | nM = size(lamda,1); 110 | fqmodes = lamda; 111 | ffreqq = abs(imag(fqmodes))/2/pi; 112 | fnfreqq = abs(fqmodes); 113 | fdampq = -cos(atan2(imag(fqmodes),real(fqmodes))); 114 | end 115 | 116 | %% Small Signal Analysis 117 | 118 | [frso,idxef] = sort(ffreqq,'ascend'); 119 | 120 | 121 | fqmodes = fqmodes(idxef); 122 | ffreqq = ffreqq(idxef); 123 | fdampq = fdampq(idxef); 124 | 125 | 126 | if flagMethod==1 127 | fprintf(1,'\n All Estimated Modes using ERA '); 128 | end 129 | if flagMethod==2 130 | fprintf(1,'\n All Estimated Modes using PRONY '); 131 | end 132 | fprintf(1,'\n ------------------------------------------ '); 133 | header = sprintf('\n %15s %17s %10s ',... 134 | 'mode','freq(Hz)','damp (%)'); 135 | disp(header) 136 | for i=1:nM 137 | if imag(fqmodes(i))~=0 138 | % rr=mod(i,2); 139 | % if rr==1 140 | tstr = sprintf('%10.4f i%8.4f %10.4f %10.4f',... 141 | real(fqmodes(i)),imag(fqmodes(i)),ffreqq(i),fdampq(i)*100); 142 | % else 143 | % continue 144 | % end 145 | else 146 | tstr = sprintf('%10.4f ----- %10.4f %10.4f',... 147 | real(fqmodes(i)), ffreqq(i),fdampq(i)*100); 148 | end 149 | disp(tstr) 150 | end 151 | 152 | 153 | ww=find((ffreqq>=fmin) & (ffreqq<=fmax) ); 154 | 155 | nModes = size(ww,1); 156 | nMode = nModes/2; 157 | mods = fqmodes(ww); 158 | frqmode = ffreqq(ww); 159 | dampmode = fdampq(ww); 160 | 161 | 162 | fprintf(1,'\n Modes of interest within '); 163 | fprintf(1,'\n frequencies: %2.2f and %2.2f Hz ',fmin,fmax); 164 | fprintf(1,'\n ------------------------------------------ '); 165 | header = sprintf('\n %15s %17s %10s ',... 166 | 'mode','freq(Hz)','damp (%)'); 167 | disp(header) 168 | for i=1:nModes 169 | if imag(mods(i))~=0 170 | % rr=mod(i,2); 171 | % if rr==1 172 | tstr = sprintf('%10.4f i%8.4f %10.4f %10.4f',... 173 | real(mods(i)),imag(mods(i)),frqmode(i),dampmode(i)*100); 174 | % else 175 | % continue 176 | % end 177 | else 178 | tstr = sprintf('10.4f ----- %10.4f %10.4f',... 179 | real(mods(i)), frqmode(i),dampmode(i)*100); 180 | end 181 | disp(tstr) 182 | end 183 | 184 | dampmode=dampmode*100; 185 | 186 | keyboard 187 | 188 | th=acos(Damp/100); 189 | ths=pi-th; 190 | 191 | thl=acos(dampmode/100); 192 | thls=pi-thl; 193 | 194 | jj=1; kk=size(Damp,2); 195 | for i=1:1:nModes%i=1:2:nModes 196 | for m=1:1:kk 197 | SMI(jj,m)=thls(i)-ths(m); % Matrix, Single Mode Indicator(SMI) in rads 198 | end 199 | jj=jj+1; 200 | end 201 | 202 | 203 | 204 | SMIdeg=SMI*(180/pi); 205 | 206 | for m=1:kk 207 | AMI(1,m)=norm(SMI(:,m),2); %Vector, All Mode Indicator (AMI) in rads 208 | AMI_m(1,m)=min(SMI(:,m)); 209 | end 210 | 211 | 212 | 213 | 214 | AMIdeg = AMI*(180/pi); 215 | 216 | GMI = norm(AMI,2); % Gain, Global Mode Indicator (GMI) in rads 217 | GMI_m=min(AMI_m); 218 | 219 | 220 | 221 | 222 | -------------------------------------------------------------------------------- /_source/v1/04_b_Dynamic_SmallSignal_prony_only/7bus_fault.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v1/04_b_Dynamic_SmallSignal_prony_only/7bus_fault.mat -------------------------------------------------------------------------------- /_source/v1/04_b_Dynamic_SmallSignal_prony_only/Dynamic_smallsignal_example.m: -------------------------------------------------------------------------------- 1 | clear all;clc;close all 2 | 3 | %% Load time series 4 | 5 | load 7bus_fault % The 7 bus system 6 | % load KTH_Nordic32_fault % The Nordic power system 7 | 8 | 9 | %% Set input parameters and call main function 10 | 11 | time = ts; % Time vector of order Nx1 with variable time step 12 | signal = P_line; % Active power flow on relevant lines of order NxM, where M is the number of signals 13 | 14 | step_min = 0.04; % Minimum step size (full details in future documentation) 15 | var_min = 0.1;%0.3; % [0-1] Filter signals with varianza smaller than "var_min" 16 | f = [0.1,2.5]; % [fmin,fmax] Range of frequencies of interest in Hz 17 | d =[0,5,10]; % Damping values in percent (%) where the index distances will be calculated 18 | Nm =10; % Number of modes used in Prony to reconstruct the signals 19 | 20 | [ss,y0,G,det]=sssi(signal,time,step_min,var_min,f,d,Nm); 21 | 22 | ss.smi 23 | ss.ami 24 | ss.gmi 25 | 26 | %% Outputs 27 | % 28 | % ss is a structure with the actual small-signal-stability index 29 | % ss.smi single mode indicator 30 | % ss.ami all modes indicator 31 | % ss.gmi global mode indicator 32 | % 33 | % y0 is a structure with the section of signals that where used as input in Prony 34 | % y0.t time vector 35 | % y0.y signals 36 | % 37 | % G is a structure with Prony output 38 | % G.Poles detected modes 39 | % G.Res residue of each mode 40 | % G.K gain of each mode 41 | % G.that time vector 42 | % G.yhat re-constructed signal 43 | % 44 | % det is a structure summarizing information 45 | % det.l Complex value of detected modes in the range of frequency 46 | % det.f Frequency in Hz of modes 47 | % det.d Damping in percent of modes -------------------------------------------------------------------------------- /_source/v1/04_b_Dynamic_SmallSignal_prony_only/KTH_Nordic32_fault.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v1/04_b_Dynamic_SmallSignal_prony_only/KTH_Nordic32_fault.mat -------------------------------------------------------------------------------- /_source/v1/04_b_Dynamic_SmallSignal_prony_only/pronyiTesla.m: -------------------------------------------------------------------------------- 1 | function [lamda,model]=pronyiTesla(t,y,XX,tstart,tend,T,shift,tstplot,tedplot,plotFlag); 2 | %[model]=pronyanalysis(t,y,n,tstart,tend,T,shift,tstplot,tedplot,plotFlag); 3 | %Prony analysis program for fitting to a ringdown 4 | % Inputs: 5 | % t = time vector (does not need to be equally spaced) -- column vector 6 | % t(1) is assumed to be 0; if not, all time variables are shifted by t(1). 7 | % y = ringdown matrix of order N by NChan corresponding to t, each column is a different signal 8 | % n = order of the estimated model 9 | % tstart = row vector of order 1 by NChan. tstart(k) is the starting 10 | % time for analysis for y(:,k). 11 | % tend = ending times for analysis (same dimension as tstart) 12 | % shift = flag; if shift = 1, residues are shifted to t = 0. 13 | % If the data is noisy, reccomend shift = 0. 14 | % T = sample period for analysis 15 | % tsttplot = starting time for model simulation 16 | % tedplot = ending time for model simulation 17 | % plotFlag = if = 1, plot results 18 | % Outputs (structured array): 19 | % model.Poles = ringdown pole matrix -- column k is for column k of y 20 | % model.Res = ringdown residue matrix 21 | % model.K = ringdown offset row vector 22 | % model.yhat = model signal matrix 23 | % model.that = time vector for yhat (starts at tstart) 24 | % 25 | % NOTE: It is reccomended that the N/(1+NChan) < 200, where 26 | % N = total number of data points in y to be analyzed, and 27 | % NChan = number of columns in y. 28 | 29 | % Written by D. Trudnowski, 1999. 30 | % Last update, D. Trudnowski, 2005. 31 | 32 | % 1.0 Setup 33 | 34 | %Basic error checks 35 | 36 | if (size(y,2)~=size(tstart,2))|(size(y,2)~=size(tend,2)); error('Dimension error in y, tstart, tend'); end; 37 | if (size(tstart,1)~=1)|(size(tend,1)~=1); error('Dimension error in tstart or tend'); end; 38 | if (T<=0)|(tstplot>=tedplot)|(max(t)min(tstart')); error('data error'); end; 39 | if (size(t,1) ~= size(y,1))|(size(t,2)~=1); error('Dimension error in y or t'); end; 40 | 41 | %Data parameters 42 | NChannels = size(y,2); 43 | 44 | %Shift time parameters 45 | tstart = tstart-t(1); 46 | tend = tend-t(1); 47 | tstplot = tstplot-t(1); 48 | tedplot = tedplot-t(1); 49 | t = t-t(1); 50 | 51 | %Set up analysis data and calculate offset 52 | tanalysis = T*[0:1:ceil(max(tend')/T)+1]'; 53 | Nstart = zeros(1,NChannels); 54 | Nend = zeros(1,NChannels); 55 | yanal = zeros(length(tanalysis),NChannels); 56 | K = zeros(1,NChannels); 57 | for k=1:NChannels 58 | Nstart(k) = floor(tstart(k)/T)+1; 59 | Nend(k) = ceil(tend(k)/T)+1; 60 | yanal(:,k) = spline(t,y(:,k),tanalysis); 61 | K(1,k) = mean(yanal(Nstart(k):Nend(k),k)); 62 | yanal(:,k) = yanal(:,k)-K(k); 63 | end 64 | clear k 65 | 66 | %Find model order 67 | NdataPoints = Nend-Nstart+1; %Number of data points used for analysis on each channel 68 | Ntotal = sum(NdataPoints'); %Total number of data points used for Prony analysis 69 | %nOrder = round(Ntotal/(1+NChannels))-10; %Order of Linear Prediction 70 | nOrder=XX; 71 | %if (nOrder>50); nOrder=50; end; %Limit order to avoid numerical problems 72 | 73 | % 2.0 Solve Linear Prediction 74 | 75 | %Build matrix and vector 76 | for k=1:NChannels 77 | Ym = zeros(NdataPoints(k)-nOrder,nOrder); 78 | for kk=1:nOrder 79 | Ym(:,kk) = yanal(Nstart(k)+nOrder-kk:Nstart(k)-kk+NdataPoints(k)-1,k); 80 | end 81 | yv = yanal(Nstart(k)+nOrder:Nstart(k)+NdataPoints(k)-1,k); 82 | if k==1; 83 | Ymatrix = Ym; 84 | yvector = yv; 85 | else 86 | Ymatrix = [Ymatrix;Ym]; %Cancatinate the channels 87 | yvector = [yvector;yv]; 88 | end 89 | end 90 | clear Ym yv k kk 91 | % acoef = pinv(Ymatrix)*yvector; %characteristic eqn. Pseudo inverse using SVD 92 | acoef = Ymatrix\yvector; %This provides a much more accurate solution than the above line 93 | 94 | %Find poles 95 | zPoles = roots([1;-acoef]); 96 | sPoles = log(zPoles)/T; 97 | 98 | 99 | 100 | % 3.0 Solve for residues 101 | Res = zeros(nOrder,NChannels); 102 | for k=1:NChannels 103 | ZMatrix = zeros(NdataPoints(k),nOrder); 104 | for kk=1:NdataPoints(k) 105 | ZMatrix(kk,:) = (zPoles.').^(kk-1); 106 | end 107 | Res(:,k) = ZMatrix\yanal(Nstart(k):Nend(k),k); 108 | if shift==1; 109 | Res(:,k) = Res(:,k).*(zPoles.^(-Nstart(k)+1)); %Shift residues to time 0 110 | end 111 | end 112 | clear k kk 113 | 114 | % 4.0 Re-order using energy 115 | P = zeros(nOrder,NChannels); 116 | R = zeros(size(Res)); 117 | for k=1:NChannels 118 | clear E 119 | for kk=1:nOrder 120 | if abs(real(sPoles(kk)))<1e-8 121 | E(kk)=Res(kk,k)^2*(tend(k)-tstart(k)); 122 | else 123 | E(kk)=(Res(kk,k)^2/(2*real(sPoles(kk))))*(exp(2*real(sPoles(kk))*(tend(k)-tstart(k)))-1); 124 | end 125 | end 126 | E=E(:); 127 | [x,ii]=sort(E); 128 | R(:,k)=Res(ii,k); 129 | P(:,k)=sPoles(ii); 130 | M=[length(ii):-1:1]'; 131 | R(:,k)=R(M,k); 132 | P(:,k)=P(M,k); 133 | end 134 | clear M k x ii E 135 | 136 | %Simulate; 137 | that = [tstplot:T:tedplot]'; 138 | yhat = zeros(length(that),NChannels); 139 | for k=1:NChannels 140 | yhat(:,k) = K(k).*ones(size(that)); 141 | for kk=1:length(that); 142 | for n=1:nOrder; 143 | yhat(kk,k) = yhat(kk,k) + R(n,k)*exp(P(n,k)*that(kk)); 144 | end 145 | end; 146 | end; 147 | yhat=real(yhat); 148 | 149 | % 5.0 Place output in structured array 150 | model.Poles = P; 151 | model.Res = R; 152 | model.K = K; 153 | model.that = that; 154 | model.yhat = yhat; 155 | 156 | lamda=sPoles; 157 | 158 | 159 | 160 | % 6.0 Plot results 161 | if plotFlag==1 162 | figure 163 | hold on 164 | h1 = plot(t,y); 165 | h2 = plot(that,yhat,'--*');axis tight 166 | hold off 167 | xlabel('Time (sec)') 168 | %legend('Actual','Prony') 169 | end 170 | 171 | %Original plots 172 | % if plotFlag==1 173 | % for k=1:size(yhat,2) 174 | % figure 175 | % n = find(t(t>=tstplot&t<=tedplot)); 176 | % hold on 177 | % h1 = plot(t(n),y(n,k),'k','linewidth',1.5); 178 | % h2 = plot(that,yhat(:,k),'r--','linewidth',1.5); 179 | % hold off 180 | % xlabel('Time (sec)') 181 | % legend('Actual','Prony') 182 | % end 183 | % end -------------------------------------------------------------------------------- /_source/v1/04_b_Dynamic_SmallSignal_prony_only/signal_filter.m: -------------------------------------------------------------------------------- 1 | function [ yh,osc_signal, var_s,ydh ] = signal_filter(sig,t,var_thr,step_min) 2 | % [Yh,IDX,VAR ]= signal_filter(Y,T,Thr) 3 | % Filter signal Y based on variance. The signals with threshold lower than Thr are removed. 4 | % The time vector T is required, which has variable step size. The output of the function are: 5 | % Yh- Output signal after filter 6 | % IDX- indexes of the most relevant signals 7 | % VAR-Variance of signals Y. 8 | % 9 | % If no oscillation is detected, the function gives empty matrices. 10 | 11 | 12 | 13 | nL = size(sig,2); % number of signals 14 | ts = t; % time vector with variable step 15 | trshold=var_thr; % select signals with variance higher than var_thr 16 | tsmin= step_min; % select section of signal with step size grater than step_min 17 | 18 | %% Identify disturbance on time-series with variable step 19 | 20 | tk=zeros(size(ts)); 21 | tq=zeros(size(ts)); 22 | tk(2:end)=ts(1:end-1); 23 | tm=ts-tk; 24 | tm(1)=0; %remove first element 25 | tq(3:end)=tm(2:end-1); 26 | h=tm-tq; 27 | n=size(tm,1); 28 | tr=[1:1:n]'; % line improved 29 | 30 | %figure;plot(tr,tm) 31 | 32 | hmax=max(h); 33 | 34 | jj=1; qq=1; ta=zeros(size(tm)); 35 | 36 | for i=1:n-1, 37 | ta(jj,:,qq)=tm(i); 38 | thr0(i,1)=tm(i)-tm(i+1); % 39 | if tm(i)>hmax 40 | qq=qq+1; 41 | end 42 | jj=jj+1; 43 | end 44 | 45 | p=size(ta,3); 46 | ll=size(ta,1); 47 | jj=1; 48 | tw=[];tu=[]; 49 | yy=1; 50 | pp=1; ww=0; gg=0; 51 | 52 | for i=1:p, 53 | 54 | for k=1:ll; 55 | 56 | if ta(k,:,i)>=0.0001 57 | tw(jj,1)=ta(k,:,i); 58 | tw(jj,2)=k; 59 | jj=jj+1; 60 | end 61 | 62 | if k==ll 63 | nx=size(tw,1); 64 | nm(i,1)=size(tw,1)-gg; 65 | gg=sum(nm); 66 | end 67 | 68 | end 69 | 70 | 71 | for a=yy:nx 72 | 73 | if tw(a,1)<=0.20 74 | tu(pp,1)=tw(a,1); 75 | tu(pp,2)=tw(a,2); 76 | pp=pp+1; 77 | end 78 | 79 | if a==nx 80 | jo(i,1)=size(tu,1)-ww; 81 | ww=sum(jo); 82 | end 83 | 84 | end 85 | 86 | yy=a+1; 87 | 88 | 89 | 90 | end 91 | 92 | 93 | %% Signal selection according to variance 94 | 95 | 96 | time=[]; signal=[]; osc_signal=[]; 97 | for i=1:p 98 | if jo(i)>1e-3 99 | Var(i,:)=var(sig(tu(sum(jo(1:i-1))+1,2):tu(sum(jo(1:i)),2),:)); 100 | Var_t(i,1)=sum(Var(i,:)); %Variance total 101 | if Var_t(i,1)>0.01; 102 | time=ts(tu(sum(jo(1:i-1))+1,2):tu(sum(jo(1:i)),2),:); 103 | signal=sig(tu(sum(jo(1:i-1))+1,2):tu(sum(jo(1:i)),2),:); 104 | 105 | end 106 | end 107 | end 108 | 109 | if isempty(time) 110 | osc_signal=[]; 111 | var_s=[]; 112 | yh=[]; 113 | ydh=[]; 114 | fprintf('\n Signals not suitable for SSS analysis! \n\n') 115 | else 116 | j0=1; 117 | time0=zeros(size(time)); 118 | time0(1)=time(1); 119 | time0(2:end)=time(1:end-1); 120 | dt0 =time-time0; 121 | gg=size(time,1); 122 | timex=[]; signalx=[]; 123 | for k=1:gg 124 | if dt0(k)>=tsmin 125 | dt0x(j0,1)=dt0(k); 126 | timex(j0,1)=time(k); 127 | signalx(j0,:)=signal(k,:); 128 | j0=j0+1; 129 | end 130 | end 131 | 132 | if isempty(signalx) 133 | else 134 | for k=1:nL, 135 | signalx0(:,k)=signalx(:,k)-mean(signalx(:,k)); 136 | end 137 | ydh=[timex,signalx0]; 138 | sig_var=var(signalx0)'; % variance 139 | sig_std=std(signalx0)'; % standard deviation 140 | [ var_sort,s_idx]=sort(sig_var,'descend'); 141 | [ std_sort,std_idx]=sort(sig_std,'descend'); 142 | 143 | nL0=size(var_sort,1); 144 | vA=max(var_sort); 145 | var_sort0=var_sort/vA; 146 | 147 | for k=1:nL 148 | if var_sort0(k)>= trshold; 149 | osc_signal(k,1)=s_idx(k); 150 | var_s(k,1)=var_sort(k); 151 | end 152 | end 153 | end 154 | 155 | 156 | if isempty(osc_signal) 157 | osc_signal=[]; 158 | var_s=[]; 159 | yh=[]; 160 | ydh=[]; 161 | fprintf('\n Signals no suitable for SSS analysis! \n\n') 162 | else 163 | 164 | 165 | 166 | yh=sig(:,osc_signal); 167 | 168 | 169 | % figure;plot(ts,sig(:,osc_signal)); 170 | % title(['Sigansl witht oscillation higher than the threshold (',num2str(trshold),')']) 171 | % xlabel('Time (sec)') 172 | end 173 | end 174 | 175 | -------------------------------------------------------------------------------- /_source/v1/04_b_Dynamic_SmallSignal_prony_only/sssi.m: -------------------------------------------------------------------------------- 1 | function [ sss,out,modelb,detail ] = sssi( signal,ts,stepsize_min,variance_min,Freq,Damp,Nm) 2 | %Small-signal-stability index (SSI) function 3 | % 4 | %[ INDEX ] = sssi( signal,ts,step_min,var_min,F,D,Nm) 5 | % 6 | % OUTPUTS 7 | % 8 | % INDEX - Three layer sss index with smi, ami and gmi. 9 | % 10 | % INPUTS 11 | % signal - Active power flow of relevant lines 12 | % ts - Time vector with varable step size 13 | % step_min - Minimum varable step for signal analysis 14 | % var_min - Filter signals with varianza lower than var_min 15 | % F - [fmin,fmax] 1x2 vector with frequencies of interest in Hz 16 | % D - [d0,d1,d2] 1x3 vector with damping ratios to compute index in 17 | % percent 18 | % Nm - Number of modes used in Prony to reconstruc input signals 19 | % 20 | % 21 | % * Empty matrices will be delivered if input signals used are not 22 | % suitable for sss analysis 23 | 24 | 25 | [yh,x,l,yhd]=signal_filter(signal,ts,variance_min,stepsize_min); 26 | 27 | if isempty(yhd) 28 | out=[]; 29 | sss.smi=[]; 30 | sss.ami=[]; 31 | sss.gmi=[]; 32 | modelb=[]; 33 | detail.l=[]; 34 | detail.f=[]; 35 | detail.d=[]; 36 | else 37 | 38 | t = yhd(:,1); 39 | y = yhd(:,x+1); 40 | 41 | figure;plot(t,y); 42 | 43 | out.t =t; 44 | out.y =y; 45 | 46 | %% 47 | fmin= Freq(1); % Remove frequencies less than fmin Hz 48 | fmax= Freq(2); % Remove frequencies greater than fmax Hz 49 | dmax=0.25; % Remove modes with damping greater than dmax 50 | Nm; % Number of modes used to reconstruct signals using Prony 51 | 52 | sig=y(:,:); 53 | nL=size(sig,2); 54 | 55 | [lamda,modelb]=pronyiTesla(t,sig,Nm,t(1)*ones(1,nL),t(end)*ones(1,nL),0.1,1,t(1),t(end),1); 56 | 57 | Poles.sys=diag(lamda); 58 | 59 | n_modes1 = size(lamda,1); %number of modes 60 | fmodes0 = abs(imag(lamda))/2/pi; % frequency of modes in Hz 61 | dmodes0 = -cos(atan2(imag(lamda),real(lamda))); %damping of modes 62 | 63 | [fmodes1,mode_idx1]=sort(fmodes0,'ascend'); %sorted frequencies 64 | dmodes1=dmodes0(mode_idx1); %sorted dampings 65 | 66 | jj=1; kk=1; 67 | for i=1:n_modes1, 68 | 69 | if (fmodes1(i)>=fmin)&(fmodes1(i)<=fmax) %modes within fmin and fmax 70 | fmodes2(jj,1)=fmodes1(i); 71 | dmodes2(jj,1)=dmodes1(i); 72 | mode_idx2(jj,1)=mode_idx1(i); 73 | if dmodes2(jj,1)<=dmax % discard modes with large damping ratio 74 | fmodes3(kk,1)=fmodes2(jj); 75 | dmodes3(kk,1)=dmodes2(jj); 76 | mode_idx3(kk,1)=mode_idx2(jj); 77 | kk=kk+1; 78 | end 79 | jj=jj+1; 80 | end 81 | 82 | end 83 | 84 | n_modes2=size(fmodes3,1); 85 | jj=[1:2:n_modes2]'; 86 | fmodes=fmodes3(jj); 87 | dmodes=dmodes3(jj); 88 | 89 | fprintf('\n f(Hz) d(%%) \n') 90 | fprintf('--------------') 91 | for i=1:n_modes2/2 92 | fprintf('\n%-7.3f %-7.3f ',fmodes(i),dmodes(i)*100) 93 | end 94 | fprintf('\n\n') 95 | 96 | detail.l=lamda(mode_idx3); 97 | detail.f=fmodes0(mode_idx3); 98 | detail.d=dmodes0(mode_idx3); 99 | 100 | 101 | %% Actual Three layer index SMI, AMI, GMI 102 | 103 | %Damp=[0,5,10]; % Damping ratios, Calculate damping distance from each mode to the specified dampings, ie [0%, 5%, 10%] 104 | 105 | th = acos(Damp/100); 106 | ths = pi-th; 107 | 108 | thl = acos(dmodes); 109 | thls = pi-thl; 110 | 111 | jj=1; kk=size(Damp,2); 112 | for i=1:1:n_modes2/2 113 | for m=1:1:kk 114 | SMI(jj,m)=thls(i)-ths(m); % Matrix, Single Mode Indicator(SMI) in rads 115 | end 116 | jj=jj+1; 117 | end 118 | 119 | for m=1:kk 120 | AMI(1,m)=min(SMI(:,m)); %Vector, All Mode Indicator (AMI) in rads 121 | end 122 | 123 | 124 | GMI=min(AMI); % Gain, Global Mode Indicator (GMI) in rads 125 | 126 | sss.smi = SMI; 127 | sss.ami = AMI; 128 | sss.gmi = GMI; 129 | 130 | end 131 | end 132 | 133 | -------------------------------------------------------------------------------- /_source/v1/05_a_Dynamic Voltage/EstimateE_and_X.m: -------------------------------------------------------------------------------- 1 | function F = EstimateE_and_X(z) 2 | 3 | global P Q V 4 | 5 | % Unknown variables, 6 | % one delta variable for each operating point. 7 | n=size(P,1); 8 | delta = z(1:n); 9 | E = z(n+1); 10 | X = z(n+2); 11 | 12 | % Power Flow Equations 13 | F = [P*X - E*V.*sin(delta) 14 | Q*X - E*V.*cos(delta) + V.^2]; -------------------------------------------------------------------------------- /_source/v1/05_a_Dynamic Voltage/Estimate_a_and_b.m: -------------------------------------------------------------------------------- 1 | function F = Estimate_a_and_b(z) 2 | global P Q 3 | 4 | % Unknown variables, 5 | % one delta variable for each operating point. 6 | 7 | a = z(1); 8 | b = z(2); 9 | 10 | % Power Flow Equations 11 | F = [a+b*P-Q]; -------------------------------------------------------------------------------- /_source/v1/05_a_Dynamic Voltage/LOAD_ALL.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v1/05_a_Dynamic Voltage/LOAD_ALL.mat -------------------------------------------------------------------------------- /_source/v1/05_a_Dynamic Voltage/LONNY_ALL.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v1/05_a_Dynamic Voltage/LONNY_ALL.mat -------------------------------------------------------------------------------- /_source/v1/05_a_Dynamic Voltage/dynamic_voltagestbility_meanvalues.m: -------------------------------------------------------------------------------- 1 | function [Pmax,Vmax,P_pvcurve,V_pvcurve,states]=dynamic_voltagestbility_meanvalues(t,Nb,Nl,BVm,LP1,LQ1,Pmax0,x0,rn,flag1,clr1,clr2,lwid,fnum) 2 | %% Estimate Pmax and Vmax 3 | % 4 | % 5 | % [Ph,Vh,x]=dynamic_voltagestbility(t,Nb,Nl,V,P,Q,x0,r0,flag1,clr1,clr2,lwid) 6 | % t - Time vector 7 | % Nb - Bus number to be analyzed 8 | % Nl - Line number to be analyzed 9 | % V - Bus Voltages vector 10 | % P - Active power flows on lines 11 | % Q - Reactive pwoer flows on lines 12 | % x0 - inital guess to compute [d,E,X] 13 | % r0 - intial guess to compute [alpha,beta] 14 | % flag1 - 0 no plots 15 | % 1 shhow plots 16 | % clr1 - color for estimated PV data 17 | % clr2 - color for actual PV data 18 | % lwid - line width for actial data 19 | 20 | % 21 | %% 22 | 23 | 24 | [lsec,nsec]=size(BVm); 25 | 26 | jj=1;nn=lsec; 27 | for i=1:nsec 28 | V1(jj:nn,1)=BVm(:,i); 29 | Vk(i,1)=mean(BVm(:,i)); 30 | P1(jj:nn,1)=LP1(:,i); 31 | Pk(i,1)=mean(LP1(:,i)); 32 | Q1(jj:nn,1)=LQ1(:,i); 33 | Qk(i,1)=mean(LQ1(:,i)); 34 | t1(jj:nn,1)=t(:,i); 35 | tk(i,1)=mean(t(:,i)); 36 | ns=size(V1,1); 37 | jj=ns+1; 38 | nn=nn+lsec; 39 | end 40 | 41 | 42 | V = Vk; 43 | P = Pk; 44 | Q = Qk; 45 | 46 | 47 | %% 48 | global V P Q 49 | 50 | 51 | 52 | x01 = x0(1)*ones(size(P)); 53 | x02 = mean(V1); 54 | x0 = [x01; x02; x0(3)]; 55 | 56 | z0 = lsqnonlin(@EstimateE_and_X,x0); 57 | 58 | delta = z0(1:length(P)); 59 | E = z0(length(P)+1); 60 | X = z0(length(P)+2); 61 | 62 | 63 | r0 = lsqnonlin(@Estimate_a_and_b,rn); 64 | 65 | alpha = r0(1); 66 | beta = r0(2); 67 | 68 | states=[delta;E;X;alpha;beta]; 69 | 70 | 71 | %--- Calculating P-V curve ---% 72 | [Pmax,Pmaxindex]=max(abs(P)); 73 | Pdirection=sign(P(Pmaxindex)); 74 | Pmax=0; Pestim=[]; Vs=[]; Vu=[]; 75 | maxPflag=0; 76 | 77 | 78 | while maxPflag==0 79 | Qestim=alpha+beta*Pmax; 80 | Vs2=E^2/2-Qestim*X+sqrt(E^4/4-X^2*Pmax^2-Qestim*X*E^2); 81 | if imag(Vs2)==0 & real(Vs2)>=0 82 | Vs=[Vs sqrt(Vs2)]; 83 | Vu=[sqrt(E^2/2-Qestim*X-sqrt(E^4/4-X^2*Pmax^2-Qestim*X*E^2)) Vu]; 84 | Pestim=[Pestim Pmax]; 85 | Pmax=Pmax+.01*Pdirection; 86 | else 87 | maxPflag=1; 88 | end 89 | end 90 | 91 | [Pmax,Pmaxindex]=max(abs(Pestim)); 92 | 93 | %--- Save the Pmax and Vmax values ---% 94 | Pmax = Pestim(Pmaxindex); 95 | Vmax = Vs(Pmaxindex); 96 | 97 | 98 | %--- Save PV curve data for plots ---% 99 | V_pvcurve = [Vs Vu]; 100 | if Pdirection >= 0 101 | P_pvcurve = [Pestim sort(Pestim,2,'descend')]; 102 | else 103 | P_pvcurve = [Pestim sort(Pestim,2,'ascend')]; 104 | end 105 | 106 | 107 | %% 108 | mm=exist('clr1'); 109 | nn=exist('lwid'); 110 | kk=exist('fnum'); 111 | if flag1==1 112 | 113 | if mm 114 | figure;plot(P,V,clr2,'linewidth',lwid) 115 | hold on;plot(P_pvcurve,V_pvcurve,clr1); 116 | legend('actual','estimated') 117 | hold on; verline(Pmax,clr1) 118 | %hold on; hline(Vmax,clr1) 119 | hold on; verline(Pmax-(Pmax*Pmax0)/100,clr1) 120 | else 121 | 122 | 123 | figure;plot(P,V,'r','linewidth',3) 124 | hold on;plot(P_pvcurve,V_pvcurve,'b'); 125 | legend('actual','estimated') 126 | hold on; verline(Pmax,'b') 127 | %hold on; hline(Vmax,'b') 128 | hold on; verline(Pmax-(Pmax*Pmax0)/100,'b:') 129 | end 130 | 131 | if kk 132 | figure(fnum);hold on;plot(P,V,clr2,'linewidth',lwid) 133 | hold on;plot(P_pvcurve,V_pvcurve,clr1); 134 | legend('actual','estimated') 135 | hold on; verline(Pmax,clr1) 136 | %hold on; hline(Vmax,clr1) 137 | hold on; verline(Pmax-(Pmax*Pmax0)/100,clr1) 138 | end 139 | 140 | 141 | end -------------------------------------------------------------------------------- /_source/v1/05_b_Voltage_Stability_Indexes/2bus-system.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v1/05_b_Voltage_Stability_Indexes/2bus-system.mat -------------------------------------------------------------------------------- /_source/v1/05_b_Voltage_Stability_Indexes/Estimate.m: -------------------------------------------------------------------------------- 1 | function F = Estimate(z) 2 | 3 | global PP QQ VV 4 | 5 | % Unknown variables, 6 | % one delta variable for each operating point. 7 | n=size(PP,1); 8 | delta = z(1:n); 9 | E = z(n+1); 10 | X = z(n+2); 11 | 12 | % Power Flow Equations 13 | F = [PP*X - E*VV.*sin(delta) 14 | QQ*X - E*VV.*cos(delta) + VV.^2]; -------------------------------------------------------------------------------- /_source/v1/05_b_Voltage_Stability_Indexes/Estimate_a_b.m: -------------------------------------------------------------------------------- 1 | function F = Estimate_a_b(z) 2 | global PP QQ 3 | 4 | % Unknown variables, 5 | % one delta variable for each operating point. 6 | 7 | a = z(1); 8 | b = z(2); 9 | 10 | % Power Flow Equations 11 | F = [a+b*PP-QQ]; -------------------------------------------------------------------------------- /_source/v1/05_b_Voltage_Stability_Indexes/KTH_Nordic_trip_L32.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v1/05_b_Voltage_Stability_Indexes/KTH_Nordic_trip_L32.mat -------------------------------------------------------------------------------- /_source/v1/05_b_Voltage_Stability_Indexes/KTH_Nordic_trip_L42.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v1/05_b_Voltage_Stability_Indexes/KTH_Nordic_trip_L42.mat -------------------------------------------------------------------------------- /_source/v1/05_b_Voltage_Stability_Indexes/Voltage Stability Indexes.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_source/v1/05_b_Voltage_Stability_Indexes/Voltage Stability Indexes.docx -------------------------------------------------------------------------------- /_source/v1/05_b_Voltage_Stability_Indexes/dynamic_voltagestability_precontingency.m: -------------------------------------------------------------------------------- 1 | function [PPremax1,VPremax1,PPremax2,VPremax2,PPre_pvcurve1,VPre_pvcurve1,PPre_pvcurve2,VPre_pvcurve2,states1,states2,E_pre,X_pre,P1,V1]=dynamic_voltagestability_precontingency(t,P,V,Q,P0,Q0,V0,P2,V2,Q2,faultime,alp,bet,samples) 2 | global PP QQ VV 3 | %Pre-contingency loading conditions 4 | mm=size(V); 5 | for m=1:mm(2) 6 | s=5; 7 | PPre1=zeros(s,m); 8 | VPre1=zeros(s,m); 9 | QPre1=zeros(s,m); 10 | count_pre=0; %counting variable 11 | max=size(t); 12 | 13 | for ii=1:max 14 | if t(ii,1)=0 69 | countP_esti=countP_esti+1; 70 | Vs=[Vs sqrt(Vs2)]; 71 | Vu=[sqrt(E^2/2-Qestim*X-sqrt(E^4/4-X^2*Pmax^2-Qestim*X*E^2)) Vu]; 72 | Pestim=[Pestim Pmax]; 73 | Pmax=Pmax+.01*Pdirection; 74 | else 75 | maxPflag=1; 76 | end 77 | end 78 | for ll=2:countP_esti 79 | if(Pestim(ll)>Pestim(ll-1)) 80 | Pmax=Pestim(ll); 81 | Pmaxindex=ll; 82 | end 83 | end 84 | %--- Save the Pmax and Vmax values ---% 85 | Vmax = Vs(Pmaxindex); 86 | 87 | 88 | %--- Save PV curve data for plots ---% 89 | V_pvcurve= [Vs Vu]; 90 | if Pdirection >= 0 91 | P_pvcurve = [Pestim sort(Pestim,2,'descend')]; 92 | else 93 | P_pvcurve = [Pestim sort(Pestim,2,'ascend')]; 94 | end 95 | 96 | if ii==1 97 | PPremax1(m)=Pmax; 98 | VPremax1(m)=Vmax; 99 | if m==1 100 | PPre_pvcurve1(m,:)=P_pvcurve; 101 | VPre_pvcurve1(m,:)=V_pvcurve; 102 | kk=length(PPre_pvcurve1(m,:)); 103 | else if (m>1 && length(P_pvcurve)==kk) 104 | PPre_pvcurve1(m,:)=P_pvcurve; 105 | VPre_pvcurve1(m,:)=V_pvcurve; 106 | else if (m>1 && length(P_pvcurve)1 && length(P_pvcurve)>kk) 114 | for aa=kk:length(P_pvcurve) 115 | PPre_pvcurve1(m-1,aa)=0; 116 | VPre_pvcurve1(m-1,aa)=0; 117 | end 118 | PPre_pvcurve1(m,:)=P_pvcurve; 119 | VPre_pvcurve1(m,:)=V_pvcurve; 120 | end 121 | end 122 | end 123 | end 124 | clr='-*b'; 125 | k='b'; 126 | w=3; 127 | else 128 | PPremax2(m)=Pmax; 129 | VPremax2(m)=Vmax; 130 | if m==1 131 | PPre_pvcurve2(m,:)=P_pvcurve; 132 | VPre_pvcurve2(m,:)=V_pvcurve; 133 | bb=length(PPre_pvcurve2); 134 | else if(m>1 && length(P_pvcurve)==bb) 135 | PPre_pvcurve2(m,:)=P_pvcurve; 136 | VPre_pvcurve2(m,:)=V_pvcurve; 137 | else if (m>1 && length(P_pvcurve)1 && length(P_pvcurve)>bb) 145 | for aa=bb:length(P_pvcurve) 146 | PPre_pvcurve2(m-1,aa)=0; 147 | VPre_pvcurve2(m-1,aa)=0; 148 | end 149 | PPre_pvcurve2(m,:)=P_pvcurve; 150 | VPre_pvcurve2(m,:)=V_pvcurve; 151 | end 152 | end 153 | end 154 | end 155 | clr='-*g'; 156 | k='g'; 157 | w=1.5; 158 | end 159 | 160 | Pmax0=4;hold on; 161 | plot(PP,VV,clr,'linewidth',w) 162 | hold on (m);plot(PPre(:,m),VPre(:,m),'linewidth',w); 163 | hold on (m);plot(P_pvcurve,V_pvcurve,k); 164 | 165 | legend('actual','estimated') 166 | hold on (m); verline(Pmax,'b') 167 | hold on (m); verline(Pmax-(Pmax*Pmax0)/100,'b:') 168 | end 169 | end 170 | end 171 | -------------------------------------------------------------------------------- /_source/v1/05_b_Voltage_Stability_Indexes/hline.m: -------------------------------------------------------------------------------- 1 | function hhh=hline(y,in1,in2) 2 | % function h=hline(y, linetype, label) 3 | % 4 | % Draws a horizontal line on the current axes at the location specified by 'y'. Optional arguments are 5 | % 'linetype' (default is 'r:') and 'label', which applies a text label to the graph near the line. The 6 | % label appears in the same color as the line. 7 | % 8 | % The line is held on the current axes, and after plotting the line, the function returns the axes to 9 | % its prior hold state. 10 | % 11 | % The HandleVisibility property of the line object is set to "off", so not only does it not appear on 12 | % legends, but it is not findable by using findobj. Specifying an output argument causes the function to 13 | % return a handle to the line, so it can be manipulated or deleted. Also, the HandleVisibility can be 14 | % overridden by setting the root's ShowHiddenHandles property to on. 15 | % 16 | % h = hline(42,'g','The Answer') 17 | % 18 | % returns a handle to a green horizontal line on the current axes at y=42, and creates a text object on 19 | % the current axes, close to the line, which reads "The Answer". 20 | % 21 | % hline also supports vector inputs to draw multiple lines at once. For example, 22 | % 23 | % hline([4 8 12],{'g','r','b'},{'l1','lab2','LABELC'}) 24 | % 25 | % draws three lines with the appropriate labels and colors. 26 | % 27 | % By Brandon Kuczenski for Kensington Labs. 28 | % brandon_kuczenski@kensingtonlabs.com 29 | % 8 November 2001 30 | 31 | if length(y)>1 % vector input 32 | for I=1:length(y) 33 | switch nargin 34 | case 1 35 | linetype='r:'; 36 | label=''; 37 | case 2 38 | if ~iscell(in1) 39 | in1={in1}; 40 | end 41 | if I>length(in1) 42 | linetype=in1{end}; 43 | else 44 | linetype=in1{I}; 45 | end 46 | label=''; 47 | case 3 48 | if ~iscell(in1) 49 | in1={in1}; 50 | end 51 | if ~iscell(in2) 52 | in2={in2}; 53 | end 54 | if I>length(in1) 55 | linetype=in1{end}; 56 | else 57 | linetype=in1{I}; 58 | end 59 | if I>length(in2) 60 | label=in2{end}; 61 | else 62 | label=in2{I}; 63 | end 64 | end 65 | h(I)=hline(y(I),linetype,label); 66 | end 67 | else 68 | switch nargin 69 | case 1 70 | linetype='r:'; 71 | label=''; 72 | case 2 73 | linetype=in1; 74 | label=''; 75 | case 3 76 | linetype=in1; 77 | label=in2; 78 | end 79 | 80 | 81 | 82 | 83 | g=ishold(gca); 84 | hold on 85 | 86 | x=get(gca,'xlim'); 87 | h=plot(x,[y y],linetype); 88 | if ~isempty(label) 89 | yy=get(gca,'ylim'); 90 | yrange=yy(2)-yy(1); 91 | yunit=(y-yy(1))/yrange; 92 | if yunit<0.2 93 | text(x(1)+0.02*(x(2)-x(1)),y+0.02*yrange,label,'color',get(h,'color')) 94 | else 95 | text(x(1)+0.02*(x(2)-x(1)),y-0.02*yrange,label,'color',get(h,'color')) 96 | end 97 | end 98 | 99 | if g==0 100 | hold off 101 | end 102 | set(h,'tag','hline','handlevisibility','off') % this last part is so that it doesn't show up on legends 103 | end % else 104 | 105 | if nargout 106 | hhh=h; 107 | end 108 | 109 | 110 | -------------------------------------------------------------------------------- /_source/v1/05_b_Voltage_Stability_Indexes/indices_calculation.m: -------------------------------------------------------------------------------- 1 | function [SBI1,ABI1,GBI1,SBI2,ABI2,GBI2,DataPre1,DataPost1,DataPre2,DataPost2]=indices_calculation(PPremax,VPremax,Pmax0_pre,Pmax0_post,Vmax0_pre,P0,P1,P2,V0,V1,V2,P_pvpost,V_pvpost,PPost,VPost,PPostmax,VPostmax,P_pvpre1,V_pvpre1,P_pvpre2,V_pvpre2) 2 | global Lb 3 | for m=1:length(Lb) 4 | for kk=1:2 5 | Plim_pre=PPremax(kk,m)-(Pmax0_pre(m)*PPremax(kk,m))/100 6 | Vlim_pre=VPremax(kk,m)+(Vmax0_pre(m)*VPremax(kk,m))/100; 7 | 8 | Pmean_pre=[P0(1,m);P1;P2(kk,m)] 9 | Vmean_pre=[V0(1,m);V1;V2(kk,m)]; 10 | 11 | PLimits_pre=(Plim_pre-Pmean_pre)/Plim_pre 12 | VLimits_pre=(Vmean_pre-Vlim_pre)/Vlim_pre; 13 | 14 | % For Pre-Contingency PV curve-2 15 | Pmean_post=PPost(:,m) 16 | Vmean_post=VPost(:,m); 17 | 18 | Pmax_post=PPostmax(1,m) 19 | Vmax_post=VPostmax(1,m); 20 | 21 | Plim_post=Pmax_post-(Pmax_post*Pmax0_post(1,m))/100 22 | Vlim_post=Vmax_post+(Vmax_post*Vmax0_pre(1,m))/100; 23 | PLimits_post=(Plim_post-Pmean_post)/Plim_post; 24 | VLimits_post=(Vmean_post-Vlim_post)/Vlim_post; 25 | %% 26 | lmax=1.0; 27 | lmin=0.9; 28 | 29 | Pnom0 = find(P_pvpost(m,:)>=Pmean_pre(1)*lmin & P_pvpost(m,:)<=Pmean_pre(1)*lmax & V_pvpost(m,:)>=Vmax_post); 30 | if size(Pnom0,2)>=3 31 | Pnom0 = find(P_pvpost(m,:)>=Pmean_pre(1)*0.99 & P_pvpost(m,:)<=Pmean_pre(1)*1.01 & V_pvpost(m,:)>=Vmax_post); 32 | end 33 | if size(Pnom0,2)==0 34 | Pnom0 = find(P_pvpost(m,:)>=Pmean_pre(1)*0.9 & P_pvpost(m,:)<=Pmean_pre(1)*1.1 & V_pvpost(m,:)>=Vmax_post); 35 | end 36 | absVal=abs(Pmean_pre(1)-P_pvpost(m,Pnom0)); 37 | minVal=min(abs(Pmean_pre(1)-P_pvpost(m,Pnom0))); 38 | selVal=find(absVal==minVal); 39 | Pnom_A=Pnom0(selVal); 40 | 41 | %% 42 | Pnom1 = find(P_pvpost(m,:)>=Pmean_pre(2)*lmin & P_pvpost(m,:)<=Pmean_pre(2)*lmax & V_pvpost(m,:)>=Vmax_post); 43 | if size(Pnom1,2)>=3 44 | Pnom1 = find(P_pvpost(m,:)>=Pmean_pre(2)*0.99 & P_pvpost(m,:)<=Pmean_pre(2)*1.01 & V_pvpost(m,:)>=Vmax_post); 45 | end 46 | if size(Pnom1,2)==0 47 | Pnom1 = find(P_pvpost(m,:)>=Pmean_pre(2)*0.9 & P_pvpost(m,:)<=Pmean_pre(2)*1.1 & V_pvpost(m,:)>=Vmax_post); 48 | end 49 | absVal1=abs(Pmean_pre(2)-P_pvpost(m,Pnom1)); 50 | minVal1=min(abs(Pmean_pre(2)-P_pvpost(m,Pnom1))); 51 | selVal1=find(absVal1==minVal1); 52 | Pnom_B=Pnom1(selVal1); 53 | 54 | %% 55 | 56 | if Pmax_post>= Pmean_pre(3) 57 | Pnom2 = find(P_pvpost(m,:)>=Pmean_pre(3)*lmin & P_pvpost(m,:)<=Pmean_pre(3)*lmax & V_pvpost(m,:)>=Vmax_post); 58 | if size(Pnom2,2)>=3 59 | Pnom2 = find(P_pvpost(m,:)>=Pmean_pre(3)*0.99 & P_pvpost(m,:)<=Pmean_pre(3)*1.01 & V_pvpost(m,:)>=Vmax_post); 60 | end 61 | if (size(Pnom2,2)==0 ) 62 | Pnom2 = find(P_pvpost(m,:)>=Pmean_pre(3)*0.9 & P_pvpost(m,:)<=Pmean_pre(3)*1.1 & V_pvpost(m,:)>=Vmax_post); 63 | end 64 | absVal2=abs(Pmean_pre(3)-P_pvpost(m,Pnom2)); 65 | minVal2=min(abs(Pmean_pre(3)-P_pvpost(m,Pnom2))); 66 | selVal2=find(absVal2==minVal2); 67 | Pnom_C=Pnom2(selVal2); 68 | 69 | PnomC= P_pvpost(m,Pnom_C) 70 | VnomC= V_pvpost(m,Pnom_C); 71 | 72 | else 73 | 74 | PnomC=Pmean_pre(3); 75 | VnomC=Vmax_post; 76 | end 77 | 78 | PnomA= P_pvpost(Pnom_A); 79 | VnomA= V_pvpost(Pnom_A); 80 | 81 | PnomB= P_pvpost(Pnom_B); 82 | VnomB= V_pvpost(Pnom_B); 83 | 84 | PnomX=[PnomA;PnomB;PnomC]; 85 | VnomX=[VnomA;VnomB;VnomC]; 86 | 87 | % Vlim_post1=(VnomA-Vlim_pre)/Vlim_pre; 88 | % Vlim_post2=(VnomB-Vlim_pre)/Vlim_pre; 89 | % Vlim_post3=(VnomC-Vlim_pre)/Vlim_pre; 90 | 91 | Vlim_post1=(VnomA-Vlim_post)/Vlim_post; 92 | Vlim_post2=(VnomB-Vlim_post)/Vlim_post; 93 | Vlim_post3=(VnomC-Vlim_post)/Vlim_post; 94 | 95 | Vlim_post0=[Vlim_post1;Vlim_post2;Vlim_post3] 96 | 97 | Plim_post1=(Plim_post-PnomA)/Plim_post; 98 | Plim_post2=(Plim_post-PnomB)/Plim_post; 99 | Plim_post3=(Plim_post-PnomC)/Plim_post; 100 | 101 | Plim_post0=[Plim_post1;Plim_post2;Plim_post3] 102 | %% 103 | 104 | SBI=[ PLimits_pre(1), PLimits_pre(2), PLimits_pre(3),VLimits_pre(1),VLimits_pre(2),VLimits_pre(3);... 105 | Plim_post0(1) , Plim_post0(2) , Plim_post0(3) ,Vlim_post0(1) ,Vlim_post0(2) ,Vlim_post0(3)] 106 | %% 107 | ABI=[min(SBI(:,1)),min(SBI(:,2)),min(SBI(:,3)),min(SBI(:,4)),min(SBI(:,5)),min(SBI(:,6))] 108 | 109 | GBI=[min(ABI(1:3)),min(ABI(4:6))] 110 | %% 111 | if kk==1 112 | if m==1 113 | ll=1; 114 | PP=1; 115 | end 116 | SBI1(ll:ll+1,:)=SBI; 117 | ABI1(PP,:)=ABI; 118 | GBI1(PP,:)=GBI; 119 | DataPre1(:,:,m).limits = [Plim_pre;Vlim_pre]; 120 | DataPre1(:,:,m).mean = [P0 P1 P2(kk);V0 V1 V2(kk)]; 121 | DataPre1(:,:,m).deltas = [PLimits_pre';VLimits_pre']; 122 | DataPre1(:,:,m).curve = [P_pvpre1',V_pvpre1']; 123 | DataPost1(:,:,m).limits = [Plim_post;Vlim_post]; 124 | DataPost1(:,:,m).mean = [PnomX';VnomX']; 125 | DataPost1(:,:,m).deltas = [Plim_post0';Vlim_post0']; 126 | DataPost1(:,:,m).curve = [P_pvpost',V_pvpost']; 127 | ll=ll+2; 128 | PP=PP+1; 129 | else 130 | if m==1 131 | hh=1; 132 | qq=1; 133 | end 134 | SBI2(hh:hh+1,:)=SBI; 135 | ABI2(qq,:)=ABI; 136 | GBI2(qq,:)=GBI; 137 | 138 | DataPre2(:,:,m).limits = [Plim_pre;Vlim_pre]; 139 | DataPre2(:,:,m).mean = [P0 P1 P2(kk);V0 V1 V2(kk)]; 140 | DataPre2(:,:,m).deltas = [PLimits_pre';VLimits_pre']; 141 | DataPre2(:,:,m).curve = [P_pvpre2',V_pvpre2']; 142 | DataPost2(:,:,m).limits = [Plim_post;Vlim_post]; 143 | DataPost2(:,:,m).mean = [PnomX';VnomX']; 144 | DataPost2(:,:,m).deltas = [Plim_post0';Vlim_post0']; 145 | DataPost2(:,:,m).curve = [P_pvpost',V_pvpost']; 146 | hh=hh+2; 147 | qq=qq+1; 148 | end 149 | end 150 | 151 | end 152 | 153 | end 154 | -------------------------------------------------------------------------------- /_source/v1/05_b_Voltage_Stability_Indexes/verline.m: -------------------------------------------------------------------------------- 1 | function verline(x,linetype,label); 2 | 3 | g=ishold(gca); 4 | hold on 5 | y=get(gca,'ylim'); 6 | h=plot([x x],y,linetype); 7 | 8 | if exist('label') 9 | xx=get(gca,'xlim'); 10 | xrange=xx(2)-xx(1); 11 | xunit=(x-xx(1))/xrange; 12 | if xunit<0.8 13 | text(x+0.01*xrange,y(1)+0.1*(y(2)-y(1)),label,'color',get(h,'color')) 14 | else 15 | text(x-.05*xrange,y(1)+0.1*(y(2)-y(1)),label,'color',get(h,'color')) 16 | end 17 | end -------------------------------------------------------------------------------- /_source/v1/05_b_Voltage_Stability_Indexes/vline.m: -------------------------------------------------------------------------------- 1 | function hhh=vline(x,in1,in2) 2 | % function h=vline(x, linetype, label) 3 | % 4 | % Draws a vertical line on the current axes at the location specified by 'x'. Optional arguments are 5 | % 'linetype' (default is 'r:') and 'label', which applies a text label to the graph near the line. The 6 | % label appears in the same color as the line. 7 | % 8 | % The line is held on the current axes, and after plotting the line, the function returns the axes to 9 | % its prior hold state. 10 | % 11 | % The HandleVisibility property of the line object is set to "off", so not only does it not appear on 12 | % legends, but it is not findable by using findobj. Specifying an output argument causes the function to 13 | % return a handle to the line, so it can be manipulated or deleted. Also, the HandleVisibility can be 14 | % overridden by setting the root's ShowHiddenHandles property to on. 15 | % 16 | % h = vline(42,'g','The Answer') 17 | % 18 | % returns a handle to a green vertical line on the current axes at x=42, and creates a text object on 19 | % the current axes, close to the line, which reads "The Answer". 20 | % 21 | % vline also supports vector inputs to draw multiple lines at once. For example, 22 | % 23 | % vline([4 8 12],{'g','r','b'},{'l1','lab2','LABELC'}) 24 | % 25 | % draws three lines with the appropriate labels and colors. 26 | % 27 | % By Brandon Kuczenski for Kensington Labs. 28 | % brandon_kuczenski@kensingtonlabs.com 29 | % 8 November 2001 30 | 31 | if length(x)>1 % vector input 32 | for I=1:length(x) 33 | switch nargin 34 | case 1 35 | linetype='r:'; 36 | label=''; 37 | case 2 38 | if ~iscell(in1) 39 | in1={in1}; 40 | end 41 | if I>length(in1) 42 | linetype=in1{end}; 43 | else 44 | linetype=in1{I}; 45 | end 46 | label=''; 47 | case 3 48 | if ~iscell(in1) 49 | in1={in1}; 50 | end 51 | if ~iscell(in2) 52 | in2={in2}; 53 | end 54 | if I>length(in1) 55 | linetype=in1{end}; 56 | else 57 | linetype=in1{I}; 58 | end 59 | if I>length(in2) 60 | label=in2{end}; 61 | else 62 | label=in2{I}; 63 | end 64 | end 65 | h(I)=vline(x(I),linetype,label); 66 | end 67 | else 68 | switch nargin 69 | case 1 70 | linetype='r:'; 71 | label=''; 72 | case 2 73 | linetype=in1; 74 | label=''; 75 | case 3 76 | linetype=in1; 77 | label=in2; 78 | end 79 | 80 | 81 | 82 | 83 | g=ishold(gca); 84 | hold on 85 | 86 | y=get(gca,'ylim'); 87 | h=plot([x x],y,linetype); 88 | if length(label) 89 | xx=get(gca,'xlim'); 90 | xrange=xx(2)-xx(1); 91 | xunit=(x-xx(1))/xrange; 92 | if xunit<0.8 93 | text(x+0.01*xrange,y(1)+0.1*(y(2)-y(1)),label,'color',get(h,'color')) 94 | else 95 | text(x-.05*xrange,y(1)+0.1*(y(2)-y(1)),label,'color',get(h,'color')) 96 | end 97 | end 98 | 99 | if g==0 100 | hold off 101 | end 102 | set(h,'tag','vline','handlevisibility','off') 103 | end % else 104 | 105 | if nargout 106 | hhh=h; 107 | end 108 | 109 | 110 | -------------------------------------------------------------------------------- /_thirdparty/PronyCode_Source/00119247.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ALSETLab/TRISTAN/b69ad28d93346bc4963eedbcf5ba7c5bc7e3e01f/_thirdparty/PronyCode_Source/00119247.pdf --------------------------------------------------------------------------------