From 69472697661d4a840dabb9fd70479502e88c164f Mon Sep 17 00:00:00 2001 From: Samir Romdhani Date: Fri, 23 Jan 2026 16:53:02 +0100 Subject: [PATCH 1/5] add security analysis tutorials Signed-off-by: Samir Romdhani --- docs/img/sa/nad.png | Bin 0 -> 25315 bytes docs/index.md | 2 + docs/security-analysis.md | 159 ++++++++++++++++++ pom.xml | 1 + security-analysis/README.md | 27 +++ security-analysis/pom.xml | 62 +++++++ .../sa/SecurityAnalysisTutorials.java | 139 +++++++++++++++ .../src/main/resources/config.yml | 3 + .../src/main/resources/network.xiidm | 42 +++++ .../main/resources/simplelogger.properties | 2 + 10 files changed, 437 insertions(+) create mode 100644 docs/img/sa/nad.png create mode 100644 docs/security-analysis.md create mode 100644 security-analysis/README.md create mode 100644 security-analysis/pom.xml create mode 100644 security-analysis/src/main/java/com/powsybl/tutorials/sa/SecurityAnalysisTutorials.java create mode 100644 security-analysis/src/main/resources/config.yml create mode 100644 security-analysis/src/main/resources/network.xiidm create mode 100644 security-analysis/src/main/resources/simplelogger.properties diff --git a/docs/img/sa/nad.png b/docs/img/sa/nad.png new file mode 100644 index 0000000000000000000000000000000000000000..86b5a0edf48940938a0b1c187399d79b72d65086 GIT binary patch literal 25315 zcmeEu`9Bog`?pq=3O7aB2}wxybrg|3d)Z6KzB3pmEet~0$&!5wWgEL>%f6Fk24l-Q z#x}zYo-^H_&-41ep15=F&|T3mLW5|*J*4yLStwoE~?&)Nxds>{?@3zOQx#%{%33P zpl7X|-WNNuaW4fEPT~|^)71VUO5s!5YvE=u!{&;*wT;|t!8#~jsii={N+@3cQEnyw zys7xVKmJz)|EmT6e;Y!FU_$rk%*+hanZv`w?53|B^R$q2zf`Y25#QoP- zR#)BYP?$Vm)(Q>?!f#IQuk>XvrrM+T_r3Fm`2x*B2hsP4C;=1-^5LU933hp9eVyJ)Jh;YG5Jz_wd`7DT`?>{{ebL@t)z~PH z^Z4&)uF|RCGjSe!;8nb7ao;nMNTZ(LzsJyM!N5rJoNo|O*N%>k$Q>giul}c_Fau5w zRUF4FzA>}Yoa@yeaI_+qUJoB$EoDVDN)dlG_d68f!;5TbIL#HvE@~qz4uM1(`!F=@ zB`h{QBkfW%K=w|~PMMqU&c|8Ex@NvC_V}VA`>vf9cbbzGIJ)tkD5!}UuA@ex&_7^z zqpb%%)hOlv1-?|j{|UiBg9B2kvvF@lR_O=qb(*azPzQ9IlVSquJSZtCTNNFi3?PL1 zx*uzb-)e1ZYg>!fuuJl7Yau#5l3FR?3vMMSS*aNt236kX?TvMO96QGICq`GdLE?(g z^=FqnMD$`J&cAJbCCbCiedCJXTj7b=_)iX12iFsiDDi;{N~vh=ykTx0p4JZT>?PvZ zQ>yYD>H@rcef7KSyX6?dlIhB(vKj2n1L;@Z87GMuT$ocpvc10%5O2cT^2wI=s$lw$ zee`D|Pj68Kn}Wj|<$7(MTn>3b^v8k^3*}#ZdCc4+A03wqNIWvOzg*#&Sjpa!NRytJ z@(C{fJHSzQJdcSk#v^zbvNd>V_=+tTI!}_HPp34&-op5)=>0LOA!XTWH}-!gZAIXr z;-wau&bUs;QrpzwCq7Cfh2;Bwty2OMsyH{d+KSV-ciwK^(Sl+Y&oHOT{oi5M7tXHm zJqV_mmLE%rjTPoXCx4DNzeiHx!|bj2`W8rgwbKFNvtRG6K=@qUh2aKId%f2V^q-r6 ze~lffk3R+YEJc3(c+nbmsn}r1JrO8QbwcCW% zx4V1Q{qIymyX~}Z|8TrSo=B>8&7aMaPL|>qD}P+`Q&6SetdHO+H6IG4pr8r2(Qn00 z?g!V_x71k+9jmJNHxPmG5Gv)1c{fGC zvH1L!?nP7*&2pRG z+Wkp~whsp17qWrwtpuO0k(5z|ykJJF^f(VrtQ>w4k$i9vnOiL#Aus#@V%$n?3rog! zNh--wP#_+O+`8f$%`4CC!$}?RUGwC@WsBoQ zi`EYYp2w`Qz=i<7#Jm4xZWW0G--`V#_oH1K`Jlv)ma9rF#u zh4K1GUr`|rOo)iQm{0;)e8R7Ilwdwa-Qn;TVKEYYI# zYyIp|w&)YB`=}mYA6VP$|I?yW{T5Jvg`T8~v_g9o(q(ymCfmD^iV26-ko!7jW@bb@ z*5dn%w(nLQvB>e!(as3LBnZ6Gz4VrlkV|i}n1O-8&kg$w<$C<+*G9a`71v&9I{SoE zw+QzYlwnFt%5Bq2+h0F&HA>3(5}ql%M&NB=!4mUtQ+L?t$TF=^-=W3gpyvL^d8@x7 ze^fb4F=4W9G&T6+kB1>gF)1rT^;>Vg&4xfoa|g@m@D3KAdZ0ftKAZIW!Ga42h(C|q zfMmV)$8|vsBdwXIR3b6|%+tk)?1aa0xbSURw7d5pkc*!^bL%te&VL|eeBdSTb$t-l zIzGy*zwGt0irPI;Kt5T)-roM0vI|f25M<;CK$sva8`a zJ#YmZOBz=0-ml%D{yJK>DjX(4m{iM9tf6p9m%p5Q9 zLTXkEi#Dt0ukO8P=X(3!SW&@(6EsSf{>oKzP^we@qU};!!G1M0g!BaVMd$VZXtd!Z zw)!n{VZSZx+)#_8*Xqb;m&Su$iJA2&WNBlgIV^TC=zp{xCKMW;T*o+=WSycF`q$^$ z$zZzG#*12{qo=@H+2wOzJ!+*w09W+IY%-EiSSIjy_;%eaLSp8%|IvxbiJSbFDopBH zTL*pdn@6OZy1c05g4q75JP<`>#$;(LyBuz>bsP`XM&0Raip^KUmqdIRw5-Tk`@l?vWJQ z=Xpd_c)0oi@8_YiOY|-^_5#1OM7aHDGQ~P$IzV0iC^O}pX8T#56LpiRBl=a2hzBxL`(#dk|w=y_aynwUB&nfAB0 zlfNQNRL60WtMRtXvpn_AF8;gmTvN%mY9GSYMfrGbv!^`yf=-)d+>>){@$azHJ(?F4 zZ?~hM_;ES+0Fm(ZaGS%+LD|y5u7rk7jsEiz0=baGle3T?R(sD3;(iY;aW$Q7ck!#d zZcE<6+0Ti{B#)u!-O!7n(ph$`{5FsN%C;nl24@zzlyJPuwmO|Ma$8GYxf~aU3Bq$ z4*|1&3p<5uXSyHOYQ{COt+!XulJGHw{@<+fLm0GkJRM!U+2`scM8c)76;dNWZjmd6 z*{J&IsR%RuDDh&?%;CQLfXTPWSqFk}-)P8xwlK_zURe*oM|6*@+=%aWcZ?w5D!6{q zy6|_YYL9hvw5`R6Y&SSLclJL9Y7sunony^V_|RMpmSy+B4T?39dS5z6&PcvI7ZJcT z$fmKFm>Z2RzpRq5kj8o{77&6&xqs5K9sO(NBEpz}u1FUs$f|TC{+zASKHgr#id&eQ z$MFYV*1UKfHx{E3d99Q>z`^nBHR=q_e^ulL6E1qcD)|j5gx8}p*;**2+-uE@fBe{U zaq`5tax*2e?>^4zmC83n)U*HS6f-VRGlEyXuR(|9PnL_2&GFQJZ|VNtq=aLw{vGH^ zm33X`hIbg70v7^$>R&}#QmIdG7_F_ly)4uX7dZ?)NMJaEE;3L*RU4C}^dtGmqAC<4 zp>{GlX(HP{k{|rn^?m;bSC+PE=&%?$#Klj&(Hm11*bzUzzu|}dlOfa{>5^Y0b-QGr zPrmALBy{8IXtk-Ju$7gGkx>Fc3J@>@h{SNhMb{d?OGxvay^Nbt9m8W|Jn@c~*EUAc zQ=6a#ffmPMSIK60bu=~&s%e^WZewHPMQ8iHJU##ZR)Ati2*MM-5PQQCu~%;S!QY`t zEps#w88QZY&>CWIb9r=kcNZbY($#ff&b4(C0aH;?v9L%d)PR8p*f|4X?=o(#G*wFK zb9vOE00@*CR@F9cZIS{|E1niNFD?=cP!|XcN+hMnbMj~Y{Y?k_R*lknp5MN>O3MHi zLZSB-k3n0x+G6JsG5?T0=WhBy4bjoHqF#zkYPEl;k1rkrmP)KPScQlR&+ zrp&*+6KQaB9G6EOe|z#Nih(wXoJz3Y_w)g#d;NC*kj48e*LCDYC4{d-@{x z1~>%Cv>8tbf?5Qud*BlU!4H0a-N}JziTbxSAE!J?mKDE`0v*U>@jYzS4&B@|UVPGf ztQZwaZk`!EwXuoCVpmq&B$-o%l@IxSe0=bGds3-dxSfBj5rhKH%cCO`WB)eRaB(SR zk=GsYmu1D#(E|yQ|N2!xHk~{lP33t?N*NiMw&(~a@K48IEe(+p93Ki zj0L5o+N7_V5}fi6{~pd@=c0S)VAv-=fB&}rNlz{eml9*)M1zo-DLA=%EC_-yElyaI zv9O@Pgs+4=dv;YvdB*dt)H}=3^Jl2pR-1gaXEf`Gtg<6b`JR@(IUd#xMVb7o=97$q zN~A;t;VIJJLYjPzN>M0*&7Alkliq;w4QBs3JM9_F(5ZsGwyamov=AOn`7zbeKJxYl zXCD)1;SBg9b-CD$&7-5KK6(X@MZE`Bax?9IBUUYR_H zdBRJzZobLe0sw#?#`EN4t2q?6IP`C`I)4?r@1WysV_!CCd5^In`$Y48jx7WIRO@@i zo+Ra!PdwQRh1B+ZzoJh#L;XUv5)wbMALVg8leTG;`Xd}dgQE$t&xV8n?f9Wz=vgfi zbtQioR{wdIS;3Eooz?8^8CHa#WJ(T$>thD+-C#^I0@D+YA0u z)gDr%R!N995VikBhuhM{wNOEX4D7yqNXGnzM&V|(SI+eOuhHq2GN!7H^Rm-RCBajMT&QTr6MSldqR zowUsHq~P=q`LwvL=)wS}xr582K!cw@(tIni{*NMTdrHDf2d||tf8P+mc&Scwk0w8( zTa~fBQ-iSjjd_lG!RmXiL-4#|YA&gvzWB&2EozBJU(Bz9p7*1{@^ z$q9+Y63rB6{SRnyl0~`B+<*1r!*Wm3wLH_+BB_CM+aD4rKa9@r?46+4NcQcHRC7kELHC#!byW+nB!Hm=e00fQNOlQ30etsq# z(Q)s2er{czAz6`sF1Sw3PV-4pmQGjrk0yWTI(B5{r<@O%-+K5e>c*danz6+4`cmyH ziF4+<^Zpi%_Fa0gS6EW-087~Y%erk*iQ7^Ru?T!RNn3-T#^*8zMpy$_Nh9$(**jhc zIW+fKW&K{$(x|HaPoz(ETNFzh;N8N)!y&}=auykH#9*P}y3^X+rx=h!Hv6oa*!3tN zL%y{e&1LmeE#&b$ChEC|aG~SV3z^KZ@Sq||q7|DMrWj4RC`T09WPI3a^-g+9ntb?) zx^ja30hByYzD}GoGKpw>D0WX@&&=$o^yIJ?wwepEmgBJ=1gj6!cBP{U)hsW|Fl`qeYlQ`cf@{(j1<9LNCjSmeDe3a+_j}g zE9JaQ#&D-_v>GAt@$vW>_{sMU*1Dx+hir2=9_16~UsqeZ@Fv03Yt#Tth-rHD!H1k! zvdy}$|2v;mUn?=!DHw}Q9gor;@hv@;zcuLd0E%-L$x?!4VE4YM29;#4sI)3(vlil@ z6}z7$fd@_s_#xtg{5_%9VBqy=SH;)FWD20>$*HM0iR4}z>s$z~m9DEH+QhkLG08UV z;7?Z6K6XY3W%Oa}2PsBS^~Q?oVTD2j%iRG1-)B;a$cTn^co*bX0ij$bLRZ>tvVLiIcX zFh^``1ZkWNw$kpOXpe>IeewFkgww|(4CsBnr>!RL4GHLrgt?bWvZtrue}u`Wd!f`$ z>I!z|r~CcJva7voX={nyXn**h~mw%CTbe2lgCFEH^M-WTJ zZV06vu>NyvAcu#I^$WFi1j?pQYw(ttPz(&v*i0 z^@2%0j&1KQU-l#iLPr%h$A@cO8Ws(HmF_NPW++Vw z)b6xLf55?FLI&PXVIHtM&)lEZdH87Ri3Lmpm(PhZCiiQ@HjH)8zbP{aaqi(z0bCpdXZ_^vms0Qh#;*IcpTJQ|a$9+9~JX zqvIRf<_=|bb^a&ENBo9gp-V}&Oa19WvcI_1R=e5Vq+>H`}wVSnTu}SFZ>94SlpT(Wj)Ybig+{V8?qf0WU zMj!xp6D2Gv>TCnjs@I+T9vV{$_3$a!q|Egbpjm1g$46K=ye~ycw{*%;92cYv(f|!5 z*>;}Gqn@7evt;qpFDx=r!y%f8;n znnP`EE5lT6W`kjf4#^9OV!T}*kt^Rw~`{NC%#-={6Hs^>0%iT(m~C8~S$Z>mZ+>*=qH zN5tLeEOz=qj4V#3@uJ0UxSE-o!rZG8Cx)&z2=f!9pu~w_>W?S!>n{V0gGe23JOkV# zp#<_cpMlo;VZ{ChjDtjNftjhTQ+*@hwCT#NR)zlpiofQ1I~RA9M#Ao9UmIq{js5(Pt)yu09r)={iHo|H zI~i6ND-6#6%|=KRLGnHE>Gl`Ol%zBJB($uoQqF&xbKj$PZU`eQZM*eNUVF!e$lIHv&WUD4E(OCvWtMK2O3B7HAu`by4>#HF&9&IS}=BETO&)9bc+U;DET~J zxyz3%3&w(}#b@7)9DDgt8ZyM>L(!dR!={yR0_n|VtA`KOzD?|6?q40dyHX3Yd(nZtdv1xj&CCo3V zn9PWeNqIYL>Wj(JMs?z@j53lffZdau1x3x`o*(XUr;13u?^7r0ee<|SR2k;3^&MrH z$YEVCCAv;0s(fNEu`04khbR$ualGy3Khb z5gjiS^_z7ML4CFG&}et5O&Pa=#q7PAKU7xYk3u( z&!G>pxzNTRmO(m7 z0ArM9F(6VOAF}>xL;A5&d>71*6-U!0oNHO?eM() zN`T~n z+Ei+vAbB(;b7UkfW47}g9BaNwM&9VBWAA=i1GU2-a5nLYuZ0t zetX*CzAxX@cG>WZ#Zy?m1j#4txRd!Oz18lhV!As<4pr6zs;DmKRvF zTqT)bAOU2(+%X?oYjlqeH_2mN`*HrgNokpwGyQl$itJwK$8Cqk&s^7g$l4dZLesARFVi@HL>$ zJkM{u2}zDEe9`dJ8T;oC;^**|Edsi+%J#~nY2`&tQ%tAqBV zQA&3w?4*A}wSOkykGA8=GzIF~K!8=EQQZ1*8;mjW-8Lv?a3SEx`f?AS)G~8-PJ*E+{HRlAQ?lxw*O82E6s%(R9Ig)xa|sOd2MnWQ%5cMi+m%`!J`68@)NXN^+-Gw0VJ}%) zn#@Z#>^S^mg0o)s+CcHMQc=7vXr+;*;p8;8Vm32yZw+xbOBO6YAe>{!XOe3zo?A@l zuSQ`WoT5lPeYyDzxX2dE&GAZS#u2Z|-PvR<;1<$GEnf3jP79om*lh487LPUeY1t(W z+pG!j*&VHy>)}y(=I}dmDAXu7>rIN+-(Fl`Wn=)8O-@F2(l+_e$YGq{54$vQFI4a0 zn-X4_nM&x+6^8pvpXhxjYVt_40_a2DN;qOXF%9h}g+Xp6@^7*ZHQGd!{ZzN@-@JX7 zo}mCL%X;!@97c+H%ZE9Dx`|Ox#I)1M-V;`;ZwD-z6ozUnea*YB^_uP3eb;Pl_nAGam11c)!2k8D>sea#aGM+QfTYXLbd1=Rr ztlPn&yRV60O{?!=#W$YBI}T~EmnT0O25_hl>To z@A5lk-CJhSY!hwX{fMEn7qz=T6-JE6Kw@_by_SEeY_h%DnL%5anYnM)YzxasxUl*{ zK;{s{0cF1nl;j38^X;b)^^%RQ82Bfj%3@Q#@v6lk^_*O`#;K=QuR{dbJi7O3g_0_* ztvf?1(OwDe3=|X@Ru@<=fYXVIr4uU}XJUzrIi7N04e%t0lC~GQu%gMi@p9XzjIQ<$ z{W^d1=0Zz+ivQ-9mW*jC3WeJvid!=lmEjyv%NGc!rh9GexKsTT=S|?1ylecXwQN^X zq}-kG<0A+ks?0p(^Ijhh`n)+!Oqhu69hX{FdG`*Vnb5jZ6pV3x7tAmD@vXIaQ9J}@ zW#F}8)a9|fbcDyp#&xBd2}}IpUO0EAZ@+h{RFAc=f$Im;LoqlZ1Gd#ZZcgU|JcQB@ z4uXSsoTu~|Q|=oI2n4iv8!AhrmdpKsHN%<;_;?@ve2-x{z2d14Lmu2;e9%?o-u6fy zMZ|YgmIf@{aFd{*2+9wc%}Gv3Mso?Cy(h0!U$r4R!-2=gKRRDiuHA$SuJ+7+;A7#t zSO_+lC7Y5#lkk2_zePkh$R`b;hR&24S;VI2_(^btDnDJ6_*M8EGd z@8)?5%L|HI3TJ6>B1&Ex$j{}0cYO9s{Of7ix~i7yCNu^7TU!ctS!HhZ1B5aQLVC|+hfoz zw(zq{yx!Dzk35HOc}QeN){auq(UZKa`ciBKG~^>o)7Ha-Uq^XbWVQGn0rdJOf^Z{e zWdpf5QquQ}#z$L!d8v2%xwdIw4Ok3KiytNBGPd&GS!yx?p0&#?#W`M8u@@g7#^2sA zBKb6MqjFo=sUIQ)U}|gO>SiOze0~Af=c`20(DUjRaCbE_g*Vh8jZB5L@@D)T2%*h2 z%ljt9fW=kNm>e28#uxdBoTb*F;tb4P5#ZNL`%vn;F6`C@mGoYJ!dg7n#sHlC>%>?y zbNo24``I@l>td$!EkCh^3D28>l?#gOj0E7H z2{t}$(3rfl+;=UCiUPq+?uJ05&&diVjQm*@Wg8zOHB(~Tz=4q+ku+ecGrAoO%^`t3 zz3#ZSQ9R0MyFC5i6Pm^1jXwl;Aq&B!SG#ns_Va4ETmk} z&>7K76g0vz#?p<2F23WF-zvWDx0Oxezh0RcK_+gbVrplBgRgjl=wLi_Z~#|7n%xQE zAfF#z?XF#7>ghNc?@H|=7&^m^zO5|<@Lp<{{@h0+`-KCL1nmI)D&_TRI-Pufo?bio z)(JA@>FV-@ZU<~XSrJeKfcj9VkV0Wo>XxgehZQHBAy3BUm}9BizyRR-_aTO*P{%Z} z%x&U60BP*HjWVcxxFJ?&{9sfj$~raQ_e4Ld!qQ98p`_C7dycd(QD;vLRoig<%r|)U zR0N4WIdj9iGfZH-Et{4KCh<^-pd^IrRQyS>EKc zzQ8(go0B!;1>hcXQ5J>TR2;|3Kz6qg@<^hTdZnw+V$~M363RyLmro!g;Ne%=4$CJ5 zn~>@0A$Vz7B_h0iTQ!0p${xu9Rd`EA?s51khgBrd1d8S_e>_sH@kT#7rf?M-tY-+IJ*N(sWr zN=LreQBoLBlN+Umm`eNax8Nayl=ze5?p4gQ<*RTy`Q?NVf}Cq}%BbtI>;E#)-RDR}+PDeLBLlV@sSR#W0Qg{;G2 z++6r*_WB)KpEHOT0HFSw7|CWX{4Vf}lPrYC>gH)>eMmFcjFd@uT+_yD-16$11SH4{ z-SO`Z?--c4fPCTPpf?izfXAMqmmMSQ#uaSeC)EMmCRvZQ_NW*xnH?XJrWQtyN0BDA z_|1*!>cQiK<%rTIbKp}}BTMfkrHFrqPO}GAt$cxPu?VnWoc|tL_U#aREz>|L!1>>M zp4KS8mg;lqQQ#`t-(s@XXmj0GUHc;5U0hteaX;C$be_Tdw~6tcub2O9DlTp}LkjHv z0UI&|8)};vd0F#^^PuDW-+{!U6|!q1$F4Ef-WWIdvDJ={RX&8Qb$zw26wB>JGfR9|1H zS{mdrPmUKdV$J^f(jC7S8m@f!5ZA7aXDy-mcOgF&7z^FJKJ1GC1oTHhz@Qyp;Ey%f zYzWjYn4WlK6;X@~*ooMF5-~A>3H#Jo;PQz&aJkvtP2x4E&f&WJE+e_tHvJmN`QH@P z?in7KygH~Hzv}J9htFjz{3t^VueDh$d7bUbwh7I0vm9ZlS<;_aczg0d%$1tmo)&i@ zD)I_b>~bLBFkaJmIZtMjjwg%+)2{Z*27*W`acAv)gMC_a^Q9P7dCOiaaJfl;{8SpY zC7~!O`TF*QRxZavk^2kjH^^Q9p@j~tBlVUC&OLO)|B6{eZa_FTuVxcxA1u^qm@j*$IxLaG22<0TRyDc0( zTJj)D#grDY{X(ob9WJ=JPu6KM&zE*Z8#m?+zENaS(nh)d6a1f>wM$*&8RuoMVDn5Q zUo8+ENMv>dyyJqOae4FG-*dHUn;&w(0{y$k(b`1LF4 z;G$7$T5h4>pCZ$#lL}{-+r0Crqa*I+)Mbb}$ObXa1>0tCA-8`Eu@^(WW;Q>*CHC_&wO$L-?@8rngFW$5v;LH0EI$jxvFcg- z?i@wt4ce$J@}2lYeK(X>ODbxDZ_^NJ>~{ay#c<=!%Ae~-`M1+Kc2gN~VZQ_R`+!w# zmA_ec*J?Qfs^_iL06){0%LBaYY){hAM0tN8QWh)gHuL!E`0RFxAr1z^H0SEm_iBir`2-a-v`D!qa1q z6{qvcYBLN3UF?X&(K`GT3x@OD;*Wsk_K0I9iBxCeaiQ7vgX7h;jis@{z%vx&=$UvY z)uiedL{^QgRtjAu^}5IME35~~#i!)57z=SOS@nu~dvB?`D6vwo>i!M$7X`GN$9GC? z&s6{#oSy8um5ui5W;$nhDGQ6h8Qz{r>ufqA1_z{%iSJ#leIFMmfm(oUH>RJwIA|VX zD;A^jA)(~MT^T5h!B#F^R20kGY_b5G_^#<&R&RCW=jKCWN7?m`8Si3*mECvu-B`-q z7tbpyY1nCCa_OtaewQj;C^S-=;!=5Iewk8XmkT3Y$t>g31xe5DO-l!<*K5YH-9DLZ zpI^xxYz#h>31;Sbu<}tiC-_nCzP9~CzmD4!ARFk2E%M)gcA%mU^aPm1>#t3epL z?L)lF&~ViGUg-EB`F$yxw1DZb@N=-zGf8lGQcq1Gz=fgZsNz-+hFiachEKkowM!%y*wjW+6n8-D)|aJ+&~*^j3GVK}9r zVgIYo(8dRxV;KL#u`2tx?I(NT3?Q%Qxu7J=slr%jcSNuPYT3$&94>%a82A>|9@rT9 z*H!!71^EX*wXWOI-dm3PAbJV`5a)Hs^6D9#hHY0(1(y?TA$mN7Q2vrX=sKf%ZJLtY z++-D29W)ALV_KgzO(`vN*+HL8G!9AOwV5QPSXuz zY;89LqSxe_@nnI!ad>rTLxA6~qSS1v!N&zC{(e8i1$ML-#^n4&sHA#Ry07_+2rF%r z-Mtt2?XO(hFa3`X0O?_b4}pj_>}Yk=dIi9i&%U?@HpO*$ z6yUODZ|Sy26kpsjK;riU3QSxJ+;a|ZF9Nv@lmSNYl%**Gs!`r<-5m_C0_3jc`6NI_ zP`pDRIz&BWQo-pa`tnGfrKZRNwsi!e7HA0)pf4<7JOl+NtIh){eXes2v3ukJPlM!7 z={#*z{;an&|8j2(d@0Vt;|d7Vq9Ghm3R=ZhF5}0LWgx&WX5{X-KzC5CL}5(tdcnN5 z4Iqx!e4tI(S;oSZjcY(vMK9hv>moYY1V95N#d8ogYj@-0_~2})ts!+VAL8aJ2XrNB zC<0)R3ldw;V79wK4tB2rWaTt+ z2&j?}h(1ae$(v>Zvqxkky8<4>v(FRMU2S-W!#ymA$SvQ4mSRy;0RT-LP%ejd3;B3? zBEo4*Ei5clR6^w9E09PT=Ew(VKDy^aCWe4XdVL!>jLE(6F<`fU1Ff*0B-71g2;s|K zdHw z@%mle;VBp7!Xn^vCTe^=@Qnch*Si(WP?rA08%UWktsj&ldC2MA5;!W0zj14uM}Gq znd%kAJeGbzp4k3)5)q39RzxPJR?ns{cmvq6lOpBcUXv6Py$_g^pc)VA8Skk<;wHZ@ z2{#Wv)SKuQGO9n??~Ia{-WxR%TN@w8PESDp46JN##~=EAPslQ`wap_GP%4j_7#add z+XdGn>&QbTS<$S$`KUOEp^UgAjnOM5xIx_REhUzjAw!V;j>%wSkzEHn-GN7IAcM^} zm+GpTc?Dd8zN3Fk47I8MM#g6sd3QXjgVi^CHwrHMDbC<{%)|iO!n}UrC`6m2lx{wD?#psCZYW!N*j%vUVZX>x+aI$M}e!P%5hfk0zi%d z6t-{L&Fq`|tpqugNJ+v2aj8D6{(mxt^3tnhPhbaYrACeTw7p^NBBSC$R7Gc%t@iwP zt6syRhMH#|aG^ID8EGJ&U*7}@2HuH<#J}>%&n?Z&1l;E6hM-g4W&_gyBoKEsW)`mM z;Gn3e=j%H^*Rm($Gv@gF$x*KauhG~1r;YXNaYm6srcbw9=~S?F*exd{OQMX=Nt{u# zQ2i6s^l+nUl>Lc;QAFa_v+5^)q&RFN|B+c?(@|B`w*i?k`0gt`gSe-gmrQfdTLHHB z^%4zkfYCp&ahuX<7gSNEO6nX9D6V=Zh=aXrw0+q)TdF=hJ?**u5^SVO&fi|bsnEP; z=&+MlS1_UJu+X|QIyx^+dVlt9o6oeHE4u!OkI!GIMv1(T)Bpi&z3A6ub8ND57SYUlXEaq&>kHf96(&Hax5@!m^?gKj;pCz?2b?U)paLeDai^z zM%Z#{h^`)4gU}X7YN%Tkj_bt@5Gn%Yy}APQeG!VKTjLksbVeUU1g7yI#`g%8P^8) zwR(J7$s_ox#a?k;#)E1jM({|+y0-RaPVr$gWll8%md21ajDWLuaw;g0a{4aHEcpcK zWU@C|nb%0jTy3H5p7C329m?rQ57__B6~$ab+*Fj9fz2YDP(BmZ{(%STUXkikK;d*| zBoD9O#dIKVM8vBL37l-W6gk&CI)otiJ9(Yd<5SG5z8Nju3MHzku1RY(+^jR3IULWVH?UAEM(J?q?nJ!&Fg$d zhIi&d32x3qJ3Vv>7Use}o1IfG328N>M|0FwIqD%ZDGuH7wB>RLN%F~q!uMibtwPZz zoU+e;_o@c9T^)C&&`G!m;1wttc?&w<@qCnUX*AMD_$1zcz=<|aOtrbcikZh?{<*?e zurl$!YA!XN)FY}FEhzsW-BGPyOdYPVcRbiM7MuLZfz@0FmM{{VF@LbR*n~>??5rk! zOHHC*i#W&daTYAPe=D01L|L5JI7c{E!wuGE&dWzGHMmzoOq~jyv zT9tFLdATwxwxF*o`eyB6Mo4yAe4(+u!=j6O=8Kq_Px#!=vE_2T*hU9@|Ni=KH}9&v znxu)ePQcs$xUA5sSOk<@H%t{0x&Y$$2B`VndxR9^Jq@Jk)x3 z$4M*-BKST58p3z|7A63^H{{Eu)AS89X4Q?g8_47DYP_w;#*kpyWpr2PViga>;PBqz zhs-&X>?~00$#j3T|9m~QT0%+|!Yh0i#-&=S9=rLG-o2HQVSQD!WNhqMFE873ZL*;b zAO>QBh4}Ik;1GmkNU&2 z$O=W59$g;qZwf}2s+3u9-s;}Eu)lQ|I4X*C@Fu{_{&=f+?B{d}fE1S^>4O*CdhvsFYTrjBm~YY=O7s%bt=W@r__a2+y9&Wd0`B z)rrODt}C(v!RC(0%Fkc*Y0?|l?etw91^j(^qj|kzYXmKjl9u}$sG6xP)8@6i195MP zFVf?@O`g}9lLTHLGEm%iQXy4W`}+g-#&#wWnV%ofn>^Mp@8Gwb8f;_^@`OthPW-boT_i4czol4isISj zMZO|K7<0j@q6J0Yvq1)l1cl813`*^164^qium+>7AX=EWq@~OLZGB#NTl`NRhC43pC@cW*#)P<@q6H*bH$i3LwOZY>SuULpzwJ~ycyxi&G=2H&5sO-f3VKtt!X;fKQ} zE)5310kT={rggc;_%IY&C+71f7CKNq*L>QH?|1SST5LmjGtuNVv-(F1ieCuAy$eva z#?^Qe8xr3Ec`eeZpg10rU~~E7@z{3~HBF)}F!2^p50ZrYB3+s1=>S{poP(vy)d4!! zw73|Np`N~I3pysp-rKa;)C}_B$ZqxaVS7{4 zHzt%&j+Nv#XIFWTpw3IP>ga;+Fj!pgNga5{8=d!O}-b+RPU^vN$^qRjf|>6+Old;_+CE70^|1hkG@20Uux z_%pHfBgnZ|bugz3dCpu!xi$SrK;b{-w!mW< zjL}PtXnE?*8#wFpO4OXJle5m{P&sGX}^vbY|7Z0=P z_3VxPv~*sF+yK=IcDZTMQB@pJ$clqD$^FCg1`yJDFZ=+dYy-h|NjaY+kSIZU_PC!v zf5HhN@Q)%#sXl0(&5gA+Vl#E%$Jp3i;>?M>j10M~w5wt6nqOUIX8v0C_;c6NCs6SK981UUjluyS^fA3Ra_8?qMUOHqpj{NSal5q!$cEm1XSH zbnX3<+w!@9=%oTRslJDYH{%7bNjG}-F=P1-RQn*i`?XhDR*9IMH0x3?IiiN`A!-Pc zA6bX>l-<$CJ4^(m!`7!8x`!8OuwwD~EN_fBF{23R-x+>b`X-U9VZG!%o4{jOM)F=2 z>9=A@o#&{|JBqulJk9poIJ(u3BfyJJ#Li7ii?FUAZ3Xz;X1iSr){B6Oak5_E;$*!! zJB>6t(t~79IZ1>^@r9AULPFjX+-aEn(A!Rj{e$82)iyH1cJNQaB`ioP^j+dE&iyjo za?L{LuPrKWo#r%;Kv4cfAVSVxHZI0c6Ms3UuK17#Iu}8ZtJ|pa4z6X9zJ)d`M-Xty zvwR0ZLB}plD^Fd+4=n}=RWrTVqg&d3_t}}v<<7d)5HR^S-!PnwB4nmy;GaGo;H7fO zwfy^%c8w0>rJ7rj!l|Bd5{0e|eyL~w1*!4vx=l{*t%GssObQ2a{U0n*E}MXM;SkiR zb@3~i@CoM_BzBR&w^bB+hGXt6O<%V2eF1yJ!7V0Y;rF<$#;#MjL8}zsp#Bb>$QiK3 z?sA3U&VPks=RybXQSttKLj*T3Ej78nV1+q4Q+9pnW#WfW@D}DPI~FB+gdki5p0U5{ zA8BB>$HUrZ(xUN_siDS1isPVp{&{e z&47=wu!#2ecEi}1O*uZs^j8|H-FIk)6>U0I#b45gA`j8RV=qUzc~&oXuGA=I(1PN? z=P1gnDb?F*9E+oQ3#h9h^GSIl7LQ`cio`67VsyRGxD?7e9T3pfLGxZY3W_COXUbj| z|J8e!zf1JbFx54Qvs9irmJTDd*npxXr4{iQjNO}h#e@_tNYOpp9Bcmn)6RANHJNm6 z6_s@nS!^gEQ4mq2Nbh7_nxMeaMM_kZ4iN$A$tsFSbtyqwq98;;h}1|45ouCGkuE_( zOK2ewQbhs+ym)^Sf2V-tEjmfmcvpOFz850NvQSk}D z^i>2ddQNb8S(m!y9_%S!n^HaLpH27`gqtr+Z8bZc38-ICkA2&NZjJG3F+)<1oFrQ` zkL-`%mBcXUhwhEW@A)didwMf+L{u#6%Eq6w#y<@!QOrE!lCKvQFLE)##HIE68L2re z(?cV63VV-*<+K2ttG23rxpddh8Dey8WA5AmJ=tl9-7KpGP;xn(JY7a&q0WM%q zf$Mj`sj+&KogsriCM~rhBcs{`kGB8pt&kEU7oxM1T&Wa};cS|<}K)6xfrmF+ZAZ)AQp z5|E}?nP0UQzV)lB-QoJDPmSHj#P6)Ft!!87epB?F9hVu(rf9axT`dzQF=c^d*1sp+ud_59!y z%~%w6rmCfX-8h<6H`&gdKVGh=DmSa#u%cQwz~2P(?Z!9&dx=Lj1LvrD^=*wp_&;Jr zYOz=$p?eAOup8LSQ&Mt|_KFM9c38uUJ^)2b!U-&)imF9#V z;dc6G>)wvkpIHTQ*wLvJu-=rXHJ$_XR;mLfbu+sY+KQr}MVx!XB@++`?F4zYpa3s9 zzj*VBuyE4ZvXhv`<^xv$B!H(51+70;invah&m?&`+?b`qjRi^ zxAzBm>C=+}lkCxW0}pAbqah3Ys3$f9G;VOV@@k7}`3^6IGRi=G#sWGU3_ec_cF|*) zY#bd(D_LsMpo}vPMHDSp;>jZ1t)>u|4Z}o0&O(c8j_5(ji=sXuP{d5On%cfXpT6Fh z@p3V}rva0-s}nVs8O_HC2Ko9C4_8JyK=5c{W5jiYLd0Tz*bzzX-x{{QF2xm!*-H(L@} zPm4we?{PmTjghD7WnsUcURqw>+}y;kKU1cAZRhC(-wo5IHf|QA0+%>QBPrqXS_8Fd ztjt^|Io=xj!~V~_)%<|o`VHqcyNyA-*0JEt4Z*iz`Pu3!35-IQQd8!oGoREq-f|1l z1`{4b@Jn5l&TY>kD3*Q?g%YkWpu*ecJW4KCx?3sQIzOaiHI$g=IbV*Lw;DY$)}NsO zJ?HZI>Fg!s4{u0qwMRE1pslUKtpaP6KjG+b0{mLV(;nE(!y|`cR}PQ!M>)+Wg(bx_ zxSh4-I-$~r&Th*ip1j?Kh4bpjr^F>BfY<#@IaKt+<|hXLZwAV0P9B00cSGGn223hk zuz^z(gM&vow@FrVqz)lbkwZsm``>#lrVLpO4v8y*o%=_Jj>Tk>@uAnV0u?UC7jbzV zQWD)Rj;a2wP7a6@VsDwbN*8r>`A!XQ3RvWC5ZD0M!TArEk#lp#?!>At__F+~(!5Mt zy;V>#I$>^5A=n<9IxI)P~j{@yBgxr^KbdL=5+TZA?3 z=qD11C@N%oFss-qzy5Ap0?Q_4ue4!${PX=U!uKJ3eSGSe$et{=npA$KGCXIsx{jW~ zO_PlXfR=+Vijx!xK}HE2A35Vhd#{=ke-TSl|yML479v>*}pCppv(s&2`_L{`vs zz#g>rWmR~r=|g%=O8B@?#K4?qNtxIX)%SE3J!!XP>Llm zgy>;{ZVnV*wpk=*Xt2YQ^0#OTZHZ&KnZ@o7(dnB9vs{1_!NwK8r{TUbdGidX8zh{<|*=b0OWq$;s)T zG5!6M;IZ0z0jUN#r*mX93$VY@1jI{CbxATB-RK)%rD(&M_hn7k>4TFGt>iDtUvh(y zOe6={5c?}WUs?g*uI##ssdQ{8(FRYpA^b+NvW_oU=BQu7JaBB=KBv5X_MZtHeHm)e zv|ZVKi^sqM<~9xv4(7H6H&&iC49dpFCsr|IzrU z_e0~=@+xk2&WbPu*LV^0y1KH2@gTtAzRy+nfsL!v02kz1M*Q=8Z_#rom~OBIjDTaN za5JLm7UN@Mr{Fu1@LMh}v(w^zw|u9GJ^hju1DhxjlAyX{GA`aaEPQ*TtF4qYG(R9* zXD1)`j!IwbBd*WeZFrXHFbEn&5k@gm|3rhAZ&OkYC${sc_pCa#_-q2L;Ybzm6x0d< zcVv?Tl7`n??p2pFzo|z#Lc+qh-t8qesjMYozwI*2_6MBbXy(Gg+>KYZJa%8XymF7? z`<`Fu$A%S@y9kW6vr@DwWBsJ#z-JPrXMfmP2k7&;tPJi{7*kWDjcSl*`~Dm2`}^WI zZ{7gR65i_BbC!VallizncA3sTnb$SysFcU?7-uc~16!DR#QgTsY)sRe54Zp5d&(u0 zCP*X`|s=xGLyY69-eMc?rGbjQ>)@Cfx414o={Aem{zB|id!-*GX-hpvlD z7whE~=H?JmE~kS-bhrg2gsDqPk^N_d;o3W%ZyMj84I{OhM?90AxAK1`Dnq*S3D_<% z<-WYMX$`15VWx!^)$%Izk0y}BmdJNhc5aLAmz+3$NQO*P{X@q)K_(-rm@);OpgYl# zI^364i_bX{Fy1!HjPTb#!R(a#IDm!g-ukRgu-xu^=tNL=JY0f;h7{G*5`#aPc2?Wl z-EMf6;@;|1o(;JYba&vj-_R(5pjUgPsig4=^?dit&@wUICtOs-{3z|p%65H&$YD)c zIQdU5@yf}=Nb0~?#E@kfpJm3xPeU7vwbgW=dxVq;Q7x(7CfwHVjbBIw+(VR3##L1w z**%@|j8?PUyvAx(swP||@HdJy;g z)A=t_8D2=;8P*dOUr}&T!P0}(dbUmbBEsGiQs7?IcoBD{=^o77ea0No0xG{{AD(t* z&N~0+>TM{=eyU%*M@8T_u^~Qu*4!vQFnqOU0Za6aVovofEtTV}7QWia;mmkNA-bsvQ>Dg}z2j}P$SK3t!dZ8?=TQHq`E2Biq~ct!;-%$Ti0W^J zlC%N5{Pl;y7mWEm^`sah=g1Pn?)h9psFCy4nS!_C?yW{?fXk!+3Gh(L(skuzqWsFI znYdJFLjYkaY*fiLe4T;@JJ(gt3_InHl=u@3PG$0)s8{J~=fW&} z+O~TfG3BppA5_k-?+C-wwlvXK|A8$@Icm9SpcLA`GqFHG>uq(Yc=-Fn?lrx&F&D>L z{tLM!grXjul$ea?$8>LRtpai6@72kur6t=lXK3iFuM469A%Tz4(_1Ydq(u{GXmoP2 zX$7t(Ku<=*oxl&9c{hfh&sv^ZPN` zZ+*Fe6OOKp?A+<^^cu{4%@HzSC#7-S(4~~+a?Ypf5Q1CSD!^!r1hEnrg@BXhteg4(iERH8wCo#J<4Tk zRCz)1j0r_2$j*R?SU{e>j#{6oUo?FSV+J*;jp1|jym}`zphO~vI?W&R82B3$$z!)` z_~lGTpjW5)Yv1c@IG-QeySQ*)q<=WK8N)mi77{pl68@F4v}Rbju+^^CfLx~g=|aMJ zL&5VHgIH6p_P-g?@;w5vHZgHArO-H#y@`^5^EpP!ID7s|6>x%?2K4^5146!mxX_NI z(=KSMvZlGT9;8H@%}z4Z|C0QKyY104GixAz_;ia1D14)nuFmgP)&i=%9o92trPph) z9VpG%>zEk+T9_JsW?*b59c4T{$P(!L17c^_fpJ1^AHrB_5mtbl{jFJmW_?`szj)>4 z$msaE9Rz-Fv5z4F_TS-5=Z=&cxH>!Ifh}%J^b=D8bQKIh(=bk-1oQ@Gy^fTiQvC(} z`u6PrLegmp8S?Q5tI0qar~dIZKUPE+8?a2ogNG-?;S;mXzg1Dw<*0SbdXL zNIzd)NJL%D3a{A3tD_}`@d3esO|S=ra9-dY@P!xuV$a8FX%<_W>LIJdsR|#v$p)$> ze#^1N4->QTJy(K%Q;i}=^C{NPHKwa9hKIKT z$MYueU|5SzNkxSUvSRjTZ2G;kHquh3L}OwEE=Sk;`$X|~7Q%==0A1|}j&*mc@;>nQ zT4R-GU*4*$tP6gtY$;Kh$jZb>UheC)D{hqt*>4uPjJ%AIyg3983#9YjGQ{xOH*G|5 z9u&NS({h}!04LNmInAOC#d>#2dYS+RNB%l6&<^@?#XBG%Icr6G1h^^i5AOB4+A82- zUxLGNel*KWV#DkmYPj>tK+p^F-ddXN-sTj-x9N|ABh>stGun$Wu+Yuu4dR3{q=6hh%(T=p+tr7Be|}`bB_W~-(}!lpN*UxG6+0bk#q^DgwbA|$-2>E zL^9UDVpTLsr%nu41bHlj`Qvy8_)fwJ0l5ugsMEJ0z4C^@Wh~w;hEhbkAhl`}Lu&)3 zQfzIF>W*5>w|Py4lU}T_VZ;ayj8R3#S#mqoYyp{@4@s#_0`FBS2M_n1la~51H`u`Z zHoTh}cAf$fGO=Z=rv*54X#I~T6DEm~KqeqO6%`BRh9gs<0RgK*+xvq~l^W~+z7d(5 z+rV7C4#``_F?0BI^y9K9d3j$@Ob7t{)_|hI!Sb(B?0NGw+~)Wg5NQTnQdlY~C4h!j zVP1f@cf8q}j(lXXqN3tRbIZCYZBO9`Dw&-s;1|WCrP3#mU0vHJE+0{FZ>0WhM)HgL z^;gwW9Nd^H$N% z4IE*2c4ZFeJ!ZM>)i&Fe*862wsqe4PyApc;`}sdR{Qo@!T(AnmqvMlMsvDrnv&Y=T L%DDWG+fV)j8P$-m literal 0 HcmV?d00001 diff --git a/docs/index.md b/docs/index.md index bc3ed77..1b24b62 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,6 +11,7 @@ intellij.md iTools Load flow Sensitivity analysis +Security analysis Topology Diagrams Downscaling @@ -29,6 +30,7 @@ Network modifications in Groovy ## Simulation - [Create the Java code to run power flows](loadflow.md): Learn how to create the Java code to setup and run power flows - [Create the Java code to run sensitivity analyses](sensitivity-analysis.md): Learn how to create the Java code to setup and run sensitivity analyses +- [Security analyses](security-analysis.md): Learn how to use security analyses ## Topology - [Manage bus/breaker and node/breaker topology](topology.md): Learn how to manipulate topological views of the network diff --git a/docs/security-analysis.md b/docs/security-analysis.md new file mode 100644 index 0000000..82aff9d --- /dev/null +++ b/docs/security-analysis.md @@ -0,0 +1,159 @@ +--- +layout: default +--- + +# Write the Java code to perform security analysis + +In order to perform a `security analysis`, you need a `network` and at least one `contingency` (i.e. one failure) on that network, +and possibly `operator strategies` that can take `actions` to correct a default. + +### What will you build? + +This tutorial presents three use cases of security analysis simulation. +Each example follows a brief and straightforward workflow, using input data that includes an XIIDM file and at least one contingency. + +> The three workflows can be summarized as follows: +```text +Network + contingency --> Security Analysis +Network + contingency + operators strategy --> Security Analysis +Network + contingency + limit reduction --> Security Analysis +``` + + +#### Tutorial steps + +Loading the network is a common step for all workflows. Then: + +1. Define a contingency and run the security analysis. +2. Add operator strategies and reference the associated actions. +3. Configure limit reduction parameters. + + +### Import the network from an XML IIDM file + +The network we use here is available in the tutorial's resources and is described in the IIDM format. +Start by adding the following lines in the main function of the tutorial: + +```java +Network network = Network.read("network.xiidm", SecurityAnalysisTutorials.class.getResourceAsStream("/network.xiidm")); +``` +We now have a network in memory. + +The following are shown in the (Network Area Diagram) below. +- 4 `voltage levels` +- There is one `generator` in the voltage levels `VLGEN`. +- There is one `load` on the voltage levels `VLLOAD`. +- The voltage levels `VLHV1` and `VLHV2` they are connected by two parallel lines. + +![Workflow](./img/sa/nad.png){width="75%" .center-image} + +### Create a contingency + +Before creating a contingency, make sure that contingency can actually cause a network violation. +As an example, we will add a limit to the line `NHV1_NHV2_1` to simulate a default violation. + +```java +network.getLine("NHV1_NHV2_1") + .getOrCreateSelectedOperationalLimitsGroup1("DEFAULT") + .newCurrentLimits() + .setPermanentLimit(460) + .add(); +network.getLine("NHV1_NHV2_1").setSelectedOperationalLimitsGroup1("DEFAULT"); +``` + +Next, on the other line `NHV1_NHV2_2`, we can add a contingency. + +```java +Contingency contingency = Contingency.line("NHV1_NHV2_2"); +``` + +Now the security-analysis inputs are prepared, +we can run a security analysis. This is done in the following way. +```java +SecurityAnalysis.run(network, List.of(contingency)); +``` +Here are the corresponding prints in the tutorial: + +```` +:: SecurityAnalysis :: network and contingency +Pre contingency results +Post contingency results + Contingency : NHV1_NHV2_2 + Violation Value: 1008.9287882269946 MW/° + Violation Limit: 460.0 MW/° +Operator strategy results +```` + +### Create an Operator Strategy with Actions + +```java +LoadAction loadAction = new LoadActionBuilder() + .withId("loadActionId") + .withLoadId("LOAD") + .withActivePowerValue(300) + .withRelativeValue(false) + .build(); +GeneratorAction generatorAction = new GeneratorActionBuilder() + .withId("generatorActionId") + .withGeneratorId("GEN") + .withActivePowerValue(300) + .withActivePowerRelativeValue(false) + .build(); + +OperatorStrategy operatorStrategy = new OperatorStrategy("id1", ContingencyContext.specificContingency(contingency.getId()), + List.of(new ConditionalActions("stage1", new TrueCondition(), List.of(loadAction.getId(), generatorAction.getId())))); + +SecurityAnalysisRunParameters parameters = new SecurityAnalysisRunParameters(); +parameters.addOperatorStrategy(operatorStrategy); +parameters.addAction(loadAction); +parameters.addAction(generatorAction); + +// Run security analysis +SecurityAnalysis.run(network, List.of(contingency), parameters); +``` + +Here are the corresponding prints in the tutorial: +```` +:: SecurityAnalysis :: network, contingency, operator strategies and actions +Pre contingency results +Post contingency results + Contingency : NHV1_NHV2_2 + Violation Value: 1008.9287882269946 MW/° + Violation Limit: 460.0 MW/° +Operator strategy results + OperatorStrategy : id1 + Violation Value: 516.0706108379493 MW/° + Violation Limit: 460.0 MW/° +```` + +### Create a Limit Reduction + +Note that the reduction affect results as pre-contingency violations. + +As an example, we are going to reduce the current limit of `NHV1_NHV2_1` line by 10%. + +```java +// Limit Reduction +LimitReduction limitReduction = LimitReduction.builder(LimitType.CURRENT, 0.9) + .withMonitoringOnly(false) + .withContingencyContext(ContingencyContext.all()) + .build(); +parameters.addLimitReduction(limitReduction); + +// Run security analysis +SecurityAnalysis.run(network, List.of(contingency), parameters); +``` + +Here are the corresponding prints in the tutorial: + +```` +:: SecurityAnalysis :: network, contingency and limit reduction +Pre contingency results + Value: 456.7689759899928 MW/° + Limit: 460.0 MW/° +Post contingency results + Contingency : NHV1_NHV2_2 + Violation Value: 1008.9287882269946 MW/° + Violation Limit: 460.0 MW/° +Operator strategy results +```` \ No newline at end of file diff --git a/pom.xml b/pom.xml index cbc147d..97ec2bd 100644 --- a/pom.xml +++ b/pom.xml @@ -49,6 +49,7 @@ sensitivity sld-custom-node topology + security-analysis diff --git a/security-analysis/README.md b/security-analysis/README.md new file mode 100644 index 0000000..3de8e89 --- /dev/null +++ b/security-analysis/README.md @@ -0,0 +1,27 @@ +# Security Analysis tutorial + +This tutorial aims to compute security analysis on a network, loading a network Then: +- [x] Make a contingency on a line and compute a security analysis. +- [x] Add operator strategies which contains references for actions +- [x] Add limit reduction parameters + +The complete tutorial is described in the [security analysis](https://powsybl.readthedocs.io/projects/powsybl-tutorials/en/latest/security-analysis.html) powsybl-tutorials documentation. + +# How to install the security analysis simulator +The available security analysis implementations are described in the . + +In the tutorial, we use the OpenLoadFlow implementation. Please visit this page: [security analysis](https://powsybl.readthedocs.io/projects/powsybl-core/en/stable/simulation/security/implementations.html) in powsybl-core documentation for more information about it. + +# How to configure this tutorial +The configuration file is: +``` +/security-analysis/src/main/resources/config.yml +``` + +# Running the tutorial +You just need to execute the following command lines: +``` +cd /security-analysis/ +mvn clean package exec:exec@run +``` + diff --git a/security-analysis/pom.xml b/security-analysis/pom.xml new file mode 100644 index 0000000..8114137 --- /dev/null +++ b/security-analysis/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + + + com.powsybl.tutorials + powsybl-tutorials + 2.1.0-SNAPSHOT + + + security-analysis + Security analysis tutorial + + + + false + com.powsybl.tutorials.sa.SecurityAnalysisTutorials + + + + + + org.codehaus.mojo + exec-maven-plugin + + + + powsybl.config.dirs + ${project.basedir}/src/main/resources + + + + + + + + + + com.powsybl + powsybl-config-classic + + + com.powsybl + powsybl-iidm-api + + + com.powsybl + powsybl-iidm-impl + + + com.powsybl + powsybl-open-loadflow + + + org.slf4j + slf4j-simple + runtime + + + \ No newline at end of file diff --git a/security-analysis/src/main/java/com/powsybl/tutorials/sa/SecurityAnalysisTutorials.java b/security-analysis/src/main/java/com/powsybl/tutorials/sa/SecurityAnalysisTutorials.java new file mode 100644 index 0000000..1dd0c0c --- /dev/null +++ b/security-analysis/src/main/java/com/powsybl/tutorials/sa/SecurityAnalysisTutorials.java @@ -0,0 +1,139 @@ +/** + * Copyright (c) 2026, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * SPDX-License-Identifier: MPL-2.0 + */ +package com.powsybl.tutorials.sa; + +import com.powsybl.action.*; +import com.powsybl.contingency.Contingency; +import com.powsybl.contingency.ContingencyContext; +import com.powsybl.iidm.network.*; +import com.powsybl.security.SecurityAnalysis; +import com.powsybl.security.SecurityAnalysisResult; +import com.powsybl.security.SecurityAnalysisRunParameters; +import com.powsybl.security.condition.TrueCondition; +import com.powsybl.security.limitreduction.LimitReduction; +import com.powsybl.security.strategy.ConditionalActions; +import com.powsybl.security.strategy.OperatorStrategy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.util.List; + +/** + * @author Samir Romdhani {@literal } + */ +public final class SecurityAnalysisTutorials { + private static final Logger LOGGER = LoggerFactory.getLogger(SecurityAnalysisTutorials.class); + + private SecurityAnalysisTutorials() { + } + + public static void main(String[] args) { + // Network and Contingency + log(runSecurityAnalysisUseCase1()); + // Network, Contingency, Operator Strategies and Actions + log(runSecurityAnalysisUseCase2()); + // Network, Contingency, and Limit Reductions + log(runSecurityAnalysisUseCase3()); + } + + public static SecurityAnalysisResult runSecurityAnalysisUseCase1() { + Network network = Network.read("network.xml", SecurityAnalysisTutorials.class.getResourceAsStream("/network.xiidm")); + LOGGER.info(":: SecurityAnalysis :: network and contingency"); + + network.getLine("NHV1_NHV2_1") + .getOrCreateSelectedOperationalLimitsGroup1("DEFAULT") + .newCurrentLimits() + .setPermanentLimit(460).add(); + network.getLine("NHV1_NHV2_1").setSelectedOperationalLimitsGroup1("DEFAULT"); + + Contingency contingency = Contingency.line("NHV1_NHV2_2"); + return SecurityAnalysis.run(network, List.of(contingency)).getResult(); + } + + public static SecurityAnalysisResult runSecurityAnalysisUseCase2() { + Network network = Network.read("network.xml", SecurityAnalysisTutorials.class.getResourceAsStream("/network.xiidm")); + LOGGER.info(":: SecurityAnalysis :: network, contingency, operator strategies and actions"); + + network.getLine("NHV1_NHV2_1") + .getOrCreateSelectedOperationalLimitsGroup1("DEFAULT") + .newCurrentLimits() + .setPermanentLimit(460).add(); + network.getLine("NHV1_NHV2_1").setSelectedOperationalLimitsGroup1("DEFAULT"); + + Contingency contingency = Contingency.line("NHV1_NHV2_2"); + LoadAction loadAction = new LoadActionBuilder() + .withId("loadActionId") + .withLoadId("LOAD") + .withActivePowerValue(300) + .withRelativeValue(false) + .build(); + GeneratorAction generatorAction = new GeneratorActionBuilder() + .withId("generatorActionId") + .withGeneratorId("GEN") + .withActivePowerValue(300) + .withActivePowerRelativeValue(false) + .build(); + + OperatorStrategy operatorStrategy = new OperatorStrategy("id1", ContingencyContext.specificContingency(contingency.getId()), + List.of(new ConditionalActions("stage1", new TrueCondition(), List.of(loadAction.getId(), generatorAction.getId())))); + + SecurityAnalysisRunParameters parameters = new SecurityAnalysisRunParameters(); + parameters.addOperatorStrategy(operatorStrategy); + parameters.addAction(loadAction); + parameters.addAction(generatorAction); + return SecurityAnalysis.run(network, List.of(contingency), parameters).getResult(); + } + + public static SecurityAnalysisResult runSecurityAnalysisUseCase3() { + Network network = Network.read("network.xml", SecurityAnalysisTutorials.class.getResourceAsStream("/network.xiidm")); + LOGGER.info(":: SecurityAnalysis :: network, contingency and limit reduction"); + + network.getLine("NHV1_NHV2_1") + .getOrCreateSelectedOperationalLimitsGroup1("DEFAULT") + .newCurrentLimits() + .setPermanentLimit(460).add(); + network.getLine("NHV1_NHV2_1").setSelectedOperationalLimitsGroup1("DEFAULT"); + + Contingency contingency = Contingency.line("NHV1_NHV2_2"); + SecurityAnalysisRunParameters parameters = new SecurityAnalysisRunParameters(); + LimitReduction limitReduction = LimitReduction.builder(LimitType.CURRENT, 0.9) + .withMonitoringOnly(false) + .withContingencyContext(ContingencyContext.all()) + .build(); + parameters.addLimitReduction(limitReduction); + return SecurityAnalysis.run(network, List.of(contingency), parameters).getResult(); + } + + private static void log(SecurityAnalysisResult result) { + LOGGER.info("\t Pre contingency results"); + result.getPreContingencyLimitViolationsResult().getLimitViolations() + .forEach(value -> { + LOGGER.info("\t\t Value: {} MW/°", value.getValue()); + LOGGER.info("\t\t Limit: {} MW/°", value.getLimit()); + }); + LOGGER.info("\t Post contingency results"); + result.getPostContingencyResults().forEach(postContingencyResult -> { + LOGGER.info("\t\t Contingency : {}", postContingencyResult.getContingency().getId()); + postContingencyResult.getLimitViolationsResult().getLimitViolations() + .forEach(value -> { + LOGGER.info("\t\t\t Violation Value: {} MW/°", value.getValue()); + LOGGER.info("\t\t\t Violation Limit: {} MW/°", value.getLimit()); + }); + }); + LOGGER.info("\t Operator strategy results"); + result.getOperatorStrategyResults().forEach(operatorStrategyResult -> { + LOGGER.info("\t\t OperatorStrategy : {}", operatorStrategyResult.getOperatorStrategy().getId()); + operatorStrategyResult.getLimitViolationsResult().getLimitViolations() + .forEach(value -> { + LOGGER.info("\t\t\t Violation Value: {} MW/°", value.getValue()); + LOGGER.info("\t\t\t Violation Limit: {} MW/°", value.getLimit()); + }); + }); + } +} diff --git a/security-analysis/src/main/resources/config.yml b/security-analysis/src/main/resources/config.yml new file mode 100644 index 0000000..0379aef --- /dev/null +++ b/security-analysis/src/main/resources/config.yml @@ -0,0 +1,3 @@ +# This file is loaded when `powsybl.config.dirs` points to this resources directory. +security-analysis: + default-impl-name: "OpenLoadFlow" \ No newline at end of file diff --git a/security-analysis/src/main/resources/network.xiidm b/security-analysis/src/main/resources/network.xiidm new file mode 100644 index 0000000..1349874 --- /dev/null +++ b/security-analysis/src/main/resources/network.xiidm @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/security-analysis/src/main/resources/simplelogger.properties b/security-analysis/src/main/resources/simplelogger.properties new file mode 100644 index 0000000..7456f15 --- /dev/null +++ b/security-analysis/src/main/resources/simplelogger.properties @@ -0,0 +1,2 @@ +# Hide INFO logs from openloadflow +org.slf4j.simpleLogger.log.com.powsybl.openloadflow=warn From c108af711d8031caf639c82539c5158109475dff Mon Sep 17 00:00:00 2001 From: Samir Romdhani Date: Wed, 28 Jan 2026 13:46:20 +0100 Subject: [PATCH 2/5] improve used method name for tutorial Signed-off-by: Samir Romdhani --- security-analysis/README.md | 2 -- .../tutorials/sa/SecurityAnalysisTutorials.java | 13 ++++++------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/security-analysis/README.md b/security-analysis/README.md index 3de8e89..4d643f0 100644 --- a/security-analysis/README.md +++ b/security-analysis/README.md @@ -8,8 +8,6 @@ This tutorial aims to compute security analysis on a network, loading a network The complete tutorial is described in the [security analysis](https://powsybl.readthedocs.io/projects/powsybl-tutorials/en/latest/security-analysis.html) powsybl-tutorials documentation. # How to install the security analysis simulator -The available security analysis implementations are described in the . - In the tutorial, we use the OpenLoadFlow implementation. Please visit this page: [security analysis](https://powsybl.readthedocs.io/projects/powsybl-core/en/stable/simulation/security/implementations.html) in powsybl-core documentation for more information about it. # How to configure this tutorial diff --git a/security-analysis/src/main/java/com/powsybl/tutorials/sa/SecurityAnalysisTutorials.java b/security-analysis/src/main/java/com/powsybl/tutorials/sa/SecurityAnalysisTutorials.java index 1dd0c0c..8d13a5b 100644 --- a/security-analysis/src/main/java/com/powsybl/tutorials/sa/SecurityAnalysisTutorials.java +++ b/security-analysis/src/main/java/com/powsybl/tutorials/sa/SecurityAnalysisTutorials.java @@ -21,7 +21,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.*; import java.util.List; /** @@ -35,14 +34,14 @@ private SecurityAnalysisTutorials() { public static void main(String[] args) { // Network and Contingency - log(runSecurityAnalysisUseCase1()); + log(runSecurityAnalysisWithContingency()); // Network, Contingency, Operator Strategies and Actions - log(runSecurityAnalysisUseCase2()); + log(runSecurityAnalysisWithOperatorStrategyAndActions()); // Network, Contingency, and Limit Reductions - log(runSecurityAnalysisUseCase3()); + log(runSecurityAnalysisWithLimitReduction()); } - public static SecurityAnalysisResult runSecurityAnalysisUseCase1() { + public static SecurityAnalysisResult runSecurityAnalysisWithContingency() { Network network = Network.read("network.xml", SecurityAnalysisTutorials.class.getResourceAsStream("/network.xiidm")); LOGGER.info(":: SecurityAnalysis :: network and contingency"); @@ -56,7 +55,7 @@ public static SecurityAnalysisResult runSecurityAnalysisUseCase1() { return SecurityAnalysis.run(network, List.of(contingency)).getResult(); } - public static SecurityAnalysisResult runSecurityAnalysisUseCase2() { + public static SecurityAnalysisResult runSecurityAnalysisWithOperatorStrategyAndActions() { Network network = Network.read("network.xml", SecurityAnalysisTutorials.class.getResourceAsStream("/network.xiidm")); LOGGER.info(":: SecurityAnalysis :: network, contingency, operator strategies and actions"); @@ -90,7 +89,7 @@ public static SecurityAnalysisResult runSecurityAnalysisUseCase2() { return SecurityAnalysis.run(network, List.of(contingency), parameters).getResult(); } - public static SecurityAnalysisResult runSecurityAnalysisUseCase3() { + public static SecurityAnalysisResult runSecurityAnalysisWithLimitReduction() { Network network = Network.read("network.xml", SecurityAnalysisTutorials.class.getResourceAsStream("/network.xiidm")); LOGGER.info(":: SecurityAnalysis :: network, contingency and limit reduction"); From d53ae1d23b5e3847d2e7ff137b88fb896c6782d4 Mon Sep 17 00:00:00 2001 From: Samir Romdhani Date: Wed, 28 Jan 2026 14:27:15 +0100 Subject: [PATCH 3/5] add state monitor parameter for security analysis tutorials Signed-off-by: Samir Romdhani --- docs/security-analysis.md | 38 ++++++++++++++- security-analysis/README.md | 1 + .../sa/SecurityAnalysisTutorials.java | 47 +++++++++++++++++-- 3 files changed, 81 insertions(+), 5 deletions(-) diff --git a/docs/security-analysis.md b/docs/security-analysis.md index 82aff9d..58a3b88 100644 --- a/docs/security-analysis.md +++ b/docs/security-analysis.md @@ -17,6 +17,7 @@ Each example follows a brief and straightforward workflow, using input data that Network + contingency --> Security Analysis Network + contingency + operators strategy --> Security Analysis Network + contingency + limit reduction --> Security Analysis +Network + contingency + state monitor --> Security Analysis ``` @@ -27,7 +28,7 @@ Loading the network is a common step for all workflows. Then: 1. Define a contingency and run the security analysis. 2. Add operator strategies and reference the associated actions. 3. Configure limit reduction parameters. - +4. Add state monitor parameters. ### Import the network from an XML IIDM file @@ -156,4 +157,39 @@ Post contingency results Violation Value: 1008.9287882269946 MW/° Violation Limit: 460.0 MW/° Operator strategy results +```` + +### Create a state Monitor + +A state Monitor provides information about the state of elements of the network such as branch, bus and three-winding transformers + +As an example, we are going to add state monitor parameter, we will add branch and voltage levels ids that we want information about. + +```java + +Contingency contingency = Contingency.line("NHV1_NHV2_2"); +SecurityAnalysisRunParameters parameters = new SecurityAnalysisRunParameters(); +// State Monitor +StateMonitor stateMonitor = new StateMonitor(new ContingencyContext(contingency.getId(), SPECIFIC), + Set.of("NHV1_NHV2_1"), // <= branch id + Set.of("VLGEN", "VLHV1", "VLHV2", "VLLOAD"), // <= Voltage Levels id + Set.of()); +parameters.addMonitor(stateMonitor); + +// Run security analysis +SecurityAnalysis.run(network, List.of(contingency), parameters); +``` + +Here are the corresponding prints in the tutorial: +```` +:: SecurityAnalysis :: network, contingency and state Monitor +Pre contingency results +Post contingency results + Contingency : NHV1_NHV2_2 + branchResult: BranchResult{branchId='NHV1_NHV2_1', p1=610.56215354332, q1=334.0562715296571, i1=1008.9287882269946, p2=-600.9961559564288, q2=-285.3791465506596, i2=1047.8257691455576, flowTransfer=NaN} + busResult: BusResults{voltageLevelId='VLGEN', busId='NGEN', v=24.5, angle=2.3579552596552684} + busResult: BusResults{voltageLevelId='VLHV1', busId='NHV1', v=398.26472467308224, angle=0.0} + busResult: BusResults{voltageLevelId='VLHV2', busId='NHV2', v=366.58481145130054, angle=-7.499211315976122} + busResult: BusResults{voltageLevelId='VLLOAD', busId='NLOAD', v=137.74213838955504, angle=-14.464666247602445} +Operator strategy results ```` \ No newline at end of file diff --git a/security-analysis/README.md b/security-analysis/README.md index 4d643f0..c871e2d 100644 --- a/security-analysis/README.md +++ b/security-analysis/README.md @@ -4,6 +4,7 @@ This tutorial aims to compute security analysis on a network, loading a network - [x] Make a contingency on a line and compute a security analysis. - [x] Add operator strategies which contains references for actions - [x] Add limit reduction parameters +- [x] Add state monitor parameters The complete tutorial is described in the [security analysis](https://powsybl.readthedocs.io/projects/powsybl-tutorials/en/latest/security-analysis.html) powsybl-tutorials documentation. diff --git a/security-analysis/src/main/java/com/powsybl/tutorials/sa/SecurityAnalysisTutorials.java b/security-analysis/src/main/java/com/powsybl/tutorials/sa/SecurityAnalysisTutorials.java index 8d13a5b..7f68869 100644 --- a/security-analysis/src/main/java/com/powsybl/tutorials/sa/SecurityAnalysisTutorials.java +++ b/security-analysis/src/main/java/com/powsybl/tutorials/sa/SecurityAnalysisTutorials.java @@ -16,12 +16,16 @@ import com.powsybl.security.SecurityAnalysisRunParameters; import com.powsybl.security.condition.TrueCondition; import com.powsybl.security.limitreduction.LimitReduction; +import com.powsybl.security.monitor.StateMonitor; import com.powsybl.security.strategy.ConditionalActions; import com.powsybl.security.strategy.OperatorStrategy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; +import java.util.Set; + +import static com.powsybl.contingency.ContingencyContextType.SPECIFIC; /** * @author Samir Romdhani {@literal } @@ -39,6 +43,8 @@ public static void main(String[] args) { log(runSecurityAnalysisWithOperatorStrategyAndActions()); // Network, Contingency, and Limit Reductions log(runSecurityAnalysisWithLimitReduction()); + // Network, Contingency, and State Monitor + log(runSecurityAnalysisWithStateMonitor()); } public static SecurityAnalysisResult runSecurityAnalysisWithContingency() { @@ -109,13 +115,33 @@ public static SecurityAnalysisResult runSecurityAnalysisWithLimitReduction() { return SecurityAnalysis.run(network, List.of(contingency), parameters).getResult(); } + public static SecurityAnalysisResult runSecurityAnalysisWithStateMonitor() { + Network network = Network.read("network.xml", SecurityAnalysisTutorials.class.getResourceAsStream("/network.xiidm")); + LOGGER.info(":: SecurityAnalysis :: network, contingency and state Monitor"); + Contingency contingency = Contingency.line("NHV1_NHV2_2"); + SecurityAnalysisRunParameters parameters = new SecurityAnalysisRunParameters(); + StateMonitor stateMonitor = new StateMonitor(new ContingencyContext(contingency.getId(), SPECIFIC), + Set.of("NHV1_NHV2_1"), // <= branch id + Set.of("VLGEN", "VLHV1", "VLHV2", "VLLOAD"), // <= Voltage Levels id + Set.of()); + parameters.addMonitor(stateMonitor); + return SecurityAnalysis.run(network, List.of(contingency), parameters).getResult(); + } + private static void log(SecurityAnalysisResult result) { LOGGER.info("\t Pre contingency results"); - result.getPreContingencyLimitViolationsResult().getLimitViolations() - .forEach(value -> { - LOGGER.info("\t\t Value: {} MW/°", value.getValue()); - LOGGER.info("\t\t Limit: {} MW/°", value.getLimit()); + result.getPreContingencyResult().getLimitViolationsResult().getLimitViolations() + .forEach(limitViolation -> { + LOGGER.info("\t\t Value: {} MW/°", limitViolation.getValue()); + LOGGER.info("\t\t Limit: {} MW/°", limitViolation.getLimit()); }); + result.getPreContingencyResult().getNetworkResult().getBranchResults() + .forEach(branchResult -> LOGGER.info("\t\t branchResult: {}", branchResult.toString())); + result.getPreContingencyResult().getNetworkResult().getBusResults() + .forEach(busResult -> LOGGER.info("\t\t busResult: {}", busResult.toString())); + result.getPreContingencyResult().getNetworkResult().getThreeWindingsTransformerResults() + .forEach(transformerResult -> LOGGER.info("\t\t TWT Result: {}", transformerResult.toString())); + LOGGER.info("\t Post contingency results"); result.getPostContingencyResults().forEach(postContingencyResult -> { LOGGER.info("\t\t Contingency : {}", postContingencyResult.getContingency().getId()); @@ -124,7 +150,14 @@ private static void log(SecurityAnalysisResult result) { LOGGER.info("\t\t\t Violation Value: {} MW/°", value.getValue()); LOGGER.info("\t\t\t Violation Limit: {} MW/°", value.getLimit()); }); + postContingencyResult.getNetworkResult().getBranchResults() + .forEach(branchResult -> LOGGER.info("\t\t branchResult: {}", branchResult.toString())); + postContingencyResult.getNetworkResult().getBusResults() + .forEach(busResult -> LOGGER.info("\t\t busResult: {}", busResult.toString())); + postContingencyResult.getNetworkResult().getThreeWindingsTransformerResults() + .forEach(transformerResult -> LOGGER.info("\t\t TWT Result: {}", transformerResult.toString())); }); + LOGGER.info("\t Operator strategy results"); result.getOperatorStrategyResults().forEach(operatorStrategyResult -> { LOGGER.info("\t\t OperatorStrategy : {}", operatorStrategyResult.getOperatorStrategy().getId()); @@ -133,6 +166,12 @@ private static void log(SecurityAnalysisResult result) { LOGGER.info("\t\t\t Violation Value: {} MW/°", value.getValue()); LOGGER.info("\t\t\t Violation Limit: {} MW/°", value.getLimit()); }); + operatorStrategyResult.getNetworkResult().getBranchResults() + .forEach(branchResult -> LOGGER.info("\t\t branchResult: {}", branchResult.toString())); + operatorStrategyResult.getNetworkResult().getBusResults() + .forEach(busResult -> LOGGER.info("\t\t busResult: {}", busResult.toString())); + operatorStrategyResult.getNetworkResult().getThreeWindingsTransformerResults() + .forEach(transformerResult -> LOGGER.info("\t\t TWT Result: {}", transformerResult.toString())); }); } } From 7aa15adc23cb33d66526f0ea7f496c3243fff31b Mon Sep 17 00:00:00 2001 From: Samir Romdhani Date: Fri, 30 Jan 2026 10:02:48 +0100 Subject: [PATCH 4/5] Update based on review comments Signed-off-by: Samir Romdhani --- docs/security-analysis.md | 28 ++++++------- security-analysis/README.md | 12 +++--- .../sa/SecurityAnalysisTutorials.java | 39 ++++++++----------- 3 files changed, 37 insertions(+), 42 deletions(-) diff --git a/docs/security-analysis.md b/docs/security-analysis.md index 58a3b88..16d7ee4 100644 --- a/docs/security-analysis.md +++ b/docs/security-analysis.md @@ -4,12 +4,13 @@ layout: default # Write the Java code to perform security analysis -In order to perform a `security analysis`, you need a `network` and at least one `contingency` (i.e. one failure) on that network, -and possibly `operator strategies` that can take `actions` to correct a default. +A `security analysis` is a simulation run on a `network` to check for violations. +To have more information about the contingencies we want to simulate and the network elements we want to monitor +please refer to the [Powsybl security analysis](inv:powsyblcore:*:*#simulation/security/index) documentation page. -### What will you build? +## What will you build? -This tutorial presents three use cases of security analysis simulation. +This tutorial presents 4 use cases of security analysis simulation. Each example follows a brief and straightforward workflow, using input data that includes an XIIDM file and at least one contingency. > The three workflows can be summarized as follows: @@ -20,8 +21,7 @@ Network + contingency + limit reduction --> Security Analysis Network + contingency + state monitor --> Security Analysis ``` - -#### Tutorial steps +### Tutorial steps Loading the network is a common step for all workflows. Then: @@ -30,7 +30,7 @@ Loading the network is a common step for all workflows. Then: 3. Configure limit reduction parameters. 4. Add state monitor parameters. -### Import the network from an XML IIDM file +## Import the network from an XML IIDM file The network we use here is available in the tutorial's resources and is described in the IIDM format. Start by adding the following lines in the main function of the tutorial: @@ -48,7 +48,7 @@ The following are shown in the (Network Area Diagram) below. ![Workflow](./img/sa/nad.png){width="75%" .center-image} -### Create a contingency +## Create a contingency Before creating a contingency, make sure that contingency can actually cause a network violation. As an example, we will add a limit to the line `NHV1_NHV2_1` to simulate a default violation. @@ -85,7 +85,7 @@ Post contingency results Operator strategy results ```` -### Create an Operator Strategy with Actions +## Create an operator strategy with actions ```java LoadAction loadAction = new LoadActionBuilder() @@ -127,9 +127,9 @@ Operator strategy results Violation Limit: 460.0 MW/° ```` -### Create a Limit Reduction +### create a limit reduction -Note that the reduction affect results as pre-contingency violations. +Note that the limit reductions also affect the pre-contingency violations results. As an example, we are going to reduce the current limit of `NHV1_NHV2_1` line by 10%. @@ -159,11 +159,11 @@ Post contingency results Operator strategy results ```` -### Create a state Monitor +## Use state monitor -A state Monitor provides information about the state of elements of the network such as branch, bus and three-winding transformers +A `StateMonitor` provides information about the state of network elements we want to monitor such as branch, bus and three-winding transformers... -As an example, we are going to add state monitor parameter, we will add branch and voltage levels ids that we want information about. +As an example, we are going to add state monitor parameter, we will add branch and voltage levels ids that we want to monitor. ```java diff --git a/security-analysis/README.md b/security-analysis/README.md index c871e2d..2062376 100644 --- a/security-analysis/README.md +++ b/security-analysis/README.md @@ -1,15 +1,15 @@ # Security Analysis tutorial -This tutorial aims to compute security analysis on a network, loading a network Then: -- [x] Make a contingency on a line and compute a security analysis. -- [x] Add operator strategies which contains references for actions -- [x] Add limit reduction parameters -- [x] Add state monitor parameters +This tutorial aims at computing security analysis on a network. After loading a network then: +- [x] Create a contingency on a line and compute a security analysis. +- [x] Create an operator strategy containing references to actions. +- [x] Create a limit reduction. +- [x] Add a state monitor to monitor elements on the network. The complete tutorial is described in the [security analysis](https://powsybl.readthedocs.io/projects/powsybl-tutorials/en/latest/security-analysis.html) powsybl-tutorials documentation. # How to install the security analysis simulator -In the tutorial, we use the OpenLoadFlow implementation. Please visit this page: [security analysis](https://powsybl.readthedocs.io/projects/powsybl-core/en/stable/simulation/security/implementations.html) in powsybl-core documentation for more information about it. +In the tutorial, we use the OpenLoadFlow implementation. Please visit this page: [security analysis](https://powsybl.readthedocs.io/projects/powsybl-core/en/stable/simulation/security/index.html#implementation) in powsybl-core documentation for more information about it. # How to configure this tutorial The configuration file is: diff --git a/security-analysis/src/main/java/com/powsybl/tutorials/sa/SecurityAnalysisTutorials.java b/security-analysis/src/main/java/com/powsybl/tutorials/sa/SecurityAnalysisTutorials.java index 7f68869..11beb98 100644 --- a/security-analysis/src/main/java/com/powsybl/tutorials/sa/SecurityAnalysisTutorials.java +++ b/security-analysis/src/main/java/com/powsybl/tutorials/sa/SecurityAnalysisTutorials.java @@ -37,13 +37,13 @@ private SecurityAnalysisTutorials() { } public static void main(String[] args) { - // Network and Contingency + // Network and contingency log(runSecurityAnalysisWithContingency()); - // Network, Contingency, Operator Strategies and Actions + // Network, contingency, operator strategies and actions log(runSecurityAnalysisWithOperatorStrategyAndActions()); - // Network, Contingency, and Limit Reductions + // Network, contingency and limit reduction log(runSecurityAnalysisWithLimitReduction()); - // Network, Contingency, and State Monitor + // Network, contingency and state monitor log(runSecurityAnalysisWithStateMonitor()); } @@ -51,12 +51,7 @@ public static SecurityAnalysisResult runSecurityAnalysisWithContingency() { Network network = Network.read("network.xml", SecurityAnalysisTutorials.class.getResourceAsStream("/network.xiidm")); LOGGER.info(":: SecurityAnalysis :: network and contingency"); - network.getLine("NHV1_NHV2_1") - .getOrCreateSelectedOperationalLimitsGroup1("DEFAULT") - .newCurrentLimits() - .setPermanentLimit(460).add(); - network.getLine("NHV1_NHV2_1").setSelectedOperationalLimitsGroup1("DEFAULT"); - + addLimitInLine1(network); Contingency contingency = Contingency.line("NHV1_NHV2_2"); return SecurityAnalysis.run(network, List.of(contingency)).getResult(); } @@ -65,13 +60,9 @@ public static SecurityAnalysisResult runSecurityAnalysisWithOperatorStrategyAndA Network network = Network.read("network.xml", SecurityAnalysisTutorials.class.getResourceAsStream("/network.xiidm")); LOGGER.info(":: SecurityAnalysis :: network, contingency, operator strategies and actions"); - network.getLine("NHV1_NHV2_1") - .getOrCreateSelectedOperationalLimitsGroup1("DEFAULT") - .newCurrentLimits() - .setPermanentLimit(460).add(); - network.getLine("NHV1_NHV2_1").setSelectedOperationalLimitsGroup1("DEFAULT"); - + addLimitInLine1(network); Contingency contingency = Contingency.line("NHV1_NHV2_2"); + LoadAction loadAction = new LoadActionBuilder() .withId("loadActionId") .withLoadId("LOAD") @@ -99,13 +90,9 @@ public static SecurityAnalysisResult runSecurityAnalysisWithLimitReduction() { Network network = Network.read("network.xml", SecurityAnalysisTutorials.class.getResourceAsStream("/network.xiidm")); LOGGER.info(":: SecurityAnalysis :: network, contingency and limit reduction"); - network.getLine("NHV1_NHV2_1") - .getOrCreateSelectedOperationalLimitsGroup1("DEFAULT") - .newCurrentLimits() - .setPermanentLimit(460).add(); - network.getLine("NHV1_NHV2_1").setSelectedOperationalLimitsGroup1("DEFAULT"); - + addLimitInLine1(network); Contingency contingency = Contingency.line("NHV1_NHV2_2"); + SecurityAnalysisRunParameters parameters = new SecurityAnalysisRunParameters(); LimitReduction limitReduction = LimitReduction.builder(LimitType.CURRENT, 0.9) .withMonitoringOnly(false) @@ -174,4 +161,12 @@ private static void log(SecurityAnalysisResult result) { .forEach(transformerResult -> LOGGER.info("\t\t TWT Result: {}", transformerResult.toString())); }); } + + private static void addLimitInLine1(Network network) { + network.getLine("NHV1_NHV2_1") + .getOrCreateSelectedOperationalLimitsGroup1("DEFAULT") + .newCurrentLimits() + .setPermanentLimit(460).add(); + network.getLine("NHV1_NHV2_1").setSelectedOperationalLimitsGroup1("DEFAULT"); + } } From 0bba4d226ab02e8627921f199f1950de8db9f1e5 Mon Sep 17 00:00:00 2001 From: Samir Romdhani Date: Fri, 30 Jan 2026 13:31:58 +0100 Subject: [PATCH 5/5] align sections based on tutorial content Signed-off-by: Samir Romdhani --- docs/security-analysis.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/security-analysis.md b/docs/security-analysis.md index 16d7ee4..a7da3eb 100644 --- a/docs/security-analysis.md +++ b/docs/security-analysis.md @@ -21,7 +21,7 @@ Network + contingency + limit reduction --> Security Analysis Network + contingency + state monitor --> Security Analysis ``` -### Tutorial steps +## Tutorial steps Loading the network is a common step for all workflows. Then: @@ -30,7 +30,7 @@ Loading the network is a common step for all workflows. Then: 3. Configure limit reduction parameters. 4. Add state monitor parameters. -## Import the network from an XML IIDM file +### Import the network from an XML IIDM file The network we use here is available in the tutorial's resources and is described in the IIDM format. Start by adding the following lines in the main function of the tutorial: @@ -48,7 +48,7 @@ The following are shown in the (Network Area Diagram) below. ![Workflow](./img/sa/nad.png){width="75%" .center-image} -## Create a contingency +### Create a contingency Before creating a contingency, make sure that contingency can actually cause a network violation. As an example, we will add a limit to the line `NHV1_NHV2_1` to simulate a default violation. @@ -85,7 +85,7 @@ Post contingency results Operator strategy results ```` -## Create an operator strategy with actions +### Create an operator strategy with actions ```java LoadAction loadAction = new LoadActionBuilder() @@ -127,7 +127,7 @@ Operator strategy results Violation Limit: 460.0 MW/° ```` -### create a limit reduction +### Create a limit reduction Note that the limit reductions also affect the pre-contingency violations results. @@ -159,7 +159,7 @@ Post contingency results Operator strategy results ```` -## Use state monitor +### Use state monitor A `StateMonitor` provides information about the state of network elements we want to monitor such as branch, bus and three-winding transformers...