From 31266b6b97b3d28fc91c59323029b5f5678acca8 Mon Sep 17 00:00:00 2001 From: ebursch <76970916+ebursch@users.noreply.github.com> Date: Sat, 15 Aug 2026 09:00:33 -0400 Subject: [PATCH 1/9] INIT WIP: Tearing Feature add for calculating b_crit --- ...r-field penetration in tokamak plasmas.pdf | Bin 0 -> 917910 bytes .../DIIID-like_SLAYER_example/slayer_ex.ipynb | 72 +++ src/GeneralizedPerturbedEquilibrium.jl | 1 + .../CriticalResonantField.jl | 21 + .../CriticalResonantField/TorqueBalance.jl | 122 +++++ .../CriticalResonantField/bcrit_dev.ipynb | 285 +++++++++++ .../CriticalResonantField/bcrit_dev_ggj.ipynb | 208 ++++++++ src/Tearing/CriticalResonantField/gslayer.txt | 466 ++++++++++++++++++ src/Tearing/Tearing.jl | 4 +- 9 files changed, 1178 insertions(+), 1 deletion(-) create mode 100644 docs/resources/2006-Cole-Drift-magnetohydrodynamical model of error-field penetration in tokamak plasmas.pdf create mode 100644 examples/DIIID-like_SLAYER_example/slayer_ex.ipynb create mode 100644 src/Tearing/CriticalResonantField/CriticalResonantField.jl create mode 100644 src/Tearing/CriticalResonantField/TorqueBalance.jl create mode 100644 src/Tearing/CriticalResonantField/bcrit_dev.ipynb create mode 100644 src/Tearing/CriticalResonantField/bcrit_dev_ggj.ipynb create mode 100644 src/Tearing/CriticalResonantField/gslayer.txt diff --git a/docs/resources/2006-Cole-Drift-magnetohydrodynamical model of error-field penetration in tokamak plasmas.pdf b/docs/resources/2006-Cole-Drift-magnetohydrodynamical model of error-field penetration in tokamak plasmas.pdf new file mode 100644 index 0000000000000000000000000000000000000000..17ef612ec06a3dd2111741edb73f4be3e46cfdcb GIT binary patch literal 917910 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

V8 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

v6=UXxMSTfz%%r9%KYt&Ey z({i;d{20aub%*j1{Z#XMp;6scF7K~kf>U^nFMR=G$I{2imW+ulCZ4M|vX+y(W^uB0 z4MEKHlJTz^WU!>u&}G(TU(uXkNGuS@zR)K7B<#U;7!?q1-i(GRYh*_Km^Po1)`jzz zi_PxN&djCZFNL0gA@)Go5Rcn-19juW?&jTrE%~OlE04fWICPx-&M+frMlE*x+WjW) z6vHYfg(3?sY`I-?Cv@L)eQZoFDoWpLVO3p;&3!jl+I(!G-fvojy6W2eaZZzb%R91+ zZ02=)#^R)QJ<11z-?PFD8*A)-BUkC}=S%kKg@^m6q=|DV6*CIDhMIYWlJBjg1? zPL6Rys8g)MT}k4%BXl=jH}~`10H=Vs$HLD4=umkop+kf^h^PSNyoVQD^mgd}ed`&YOl3*O(9@gjnj_?@19?&^P}jIznp zHAbR_g=$_9Uu~;wxIP&xbr3v%|HVN2Xs%?9R-9u5V+Y;FRb$`bgeZ|t)cMz~=l5j% zXC0?jp=YzoOS3;5LvvM@$_d9EX*Effv3^qX3?s38!2b57vVM^;`waOp_4gg*SDq3A zOoV*JXi0DNfbZJV2MW#6zvXnD$5)GmkI-(g7ZNXQVWq`%&*()T%`Rb7p=o5X#p_b( zY~7U$a&P;6*-4oCF;RA5AoM=q2ke`d(LswEhkR=R$_mUp-ct#a#-L`>tzd1#iQZ!j zj8f%<9i>H|YDYuP7daZf*PzrRtF(8=uaq-i-lvKf;o0$c4cN4z;kQ_sTwULnXMyZi zUl{wkclsk4k5#V_vdc4tX>R*r5;O2&lf0e3O?{6^@eM`#b}hr5#3)S_ZN?0XFI#ZS zayKQ2oFiDnbiKqyD>}d^TszoM_$#^_0+a1l4)Uj^9~q(_$V0j-zVoihrz_HPxznk_1D% z?-1xje*5!`g~aZ%V+)cgE5|1JvKz+Q4>d2@)RcZ5-D`Lj6a2Z~PNl3uw`ff8k_;x- z7`(u6Hy+`~)_1N+cvU%bvluhp(x~~XKKV4;k6A%6F%xY)AIVsuia%gMxO6}njHZo8 zs9Kf=xBO~fL9?^ly*QJ|tm_qMrYBkjlk5Fr-Am^$HlFZsJXCZqqn`T;Ka(wuj-}oy ztcfLe(7DW1XE7%O!6Wi!bc+ZwBvHN?4%L(0BQ);}Vqw%;YO3=_|xa3$kXn*krxM`PyGhth#89AuXE4YhI&F z&+Rpgu@62}!`tjB%SycxmuX{HLi+wz&1t3pMPPmWIp4E{FtZbw6BQENnF3Bl#PcK$0UxH?>HncVA`5YVwNCPh-FUyX$Buy){ z#qdV?wl?kayOF3|(h>|#Z5SF8X^|)6#%x)iUW~l`yjIW~ldc$D?QIaoWcYEC%t8)F z4~%%Ycb3dW5_3Wv?TyeG%SgDSYQ-t5O@@PpOIUX5qL55i)7~KCT>g< z5#}=#_;H0-uar{!4^QAKEnhz^s%wThRx#*SwRFZ!y4aaU`{9(nv6NIrA(cVW`=LLk zRn^Oz-^8Z6QME-GDU_pHlvH=I9^2l~)mFm)&_jWS2#{=rgHd!i9m zpRH10@^tJp`O!!xGYw0Px|z%6-Keu+#=ZZNcvLN1mYC)qa=Vd>xd&nEluV)d{a25d zPF2c5b(D^CR6+vYEJH)KnCpHlwss%FmqXWGDN}#Ln$USo?%l+tk90Cdnh%sQ6=V&r zBh?`qk0Fr}jfLtv3F;(7D5%MjUTfQg^dT0eC%CW-Zqi0MXE9VyJ-b{5b#qZ>$>=?}$P#;zPTfnQK_<2$m!ndJIqG@U`niE+QP6VBsx`DCU$aK-T0Yi#} z^h*yJ<}vM0o@2@?iZ^GRyd;jnB(Pm;O3P_+Qd~4>HHh$$u-w%06k$}&m}od8{gzu5 z%56Mb9{E35UwWc!$b|jq#@VH)YKDiQ_-1+Pm`{wCn{<&tjPG^U+~n>*3a-06&=>Fw zGC&vz9=*IolL{F^(~qgxniUvc9D~<%i@`@pkERWxdz-Tn^0r8Fa%LoQL&~Z}UZwu4i_W2(M2!6l+|o zCP`ZHsf9tU@il2pp~G8v->aU8pVg@=4c{Kc5&m8q#fB@s;M^dJW4S%}Imm!X`nq97 zkE~7TdLXXv?2E~yNqvN@hNFxaQq0RfEk>6lZl<|z_^~mzn5=C5w678SA5x?{{HC27 zybRMM;aXUxuk7vyYK1>;;5zXReOrB(3omd_-VPUQ+%9zA^hxhq#aQ~vCqowBPuhCi zl$FAquNo;+MmPHQtecy@Ry1k*GztD1*^StaNZ-1iKA-VwzWKee=hSQ`R8hf={;kT+ z%_LDa(Q7DN7MmyX_p8vdF{jfaz1x!(EFP&JOWwCuj?p?~V9!&`Ii68d*PQDg-T~IN zdA&}(h4=<$aw%LBmHb@v?_Zv0kJYN{s@U52(9(~+>_?`lwKK)_Q;*N~LLY_G!t-_y zdH?-OlsqWRHj-}s9AKAoE$zk!IEjy0#PBLA*Qkh9RS)_*qoE&Chz`!4_Y zcr>iXOFh4B-D%?Oi0;b326eM%@sup^Nh6gXBC^7W(5_}DS8HSVygX-jM7tj0lMRE* zL*;&55IOYVpt;F9*&K5og>>m#29Ye``WaV# z%5~qSy}~_S6cG`Di`F`G?dIC}S^s0-N%Z8l+WayP*WA)rby1}gp?Tt^5XQ~a>>F#T zxknmstm<-tjNHs2?Bl$x1_l*lm29jU`!nY=>%iPN@fN%aPj1dJmui${NDR5X>zvAK zcnobE1p~e|HS6b&p&3ccTJ|K08D_eo)>F%~y0i&&gjhzF{pi4R0Li=Xy%z!sobC_4=nE>{F)& zKjLQyIJ&QM^gp4bd%)v2#=Ch)CHHdiCRmJBXJmg`*(7~SwSt94Aq{R8F|exOY9qHj zxL2r~Y^cUwv=q0(wb{%SlHWt+679qLo#+v$i_7QEffrQjwgD$s|M+Emc))F}`HoJ; zp?NJvY@37!d_OSCP;SMG)i_K&dRXbj!!y8$46BS5=dZwWrRo>}c=g!TqbY$+%V+R7kT7e){&HgEx0*v#KKb9p1H!M!3Z;~VNwC-e5A$Vm!#f4 zR~(e;RnjKSxA_$IHCj#@hKz7l^y9E}uju4&g)OfV;`Jp~nxW98s-940ilH9c)5RAg zL(^SG`7;&59dfMk;oKp$)sCA#j<`+v@f#aUU%18J3;0ys_riQG_db{8X*~R%TS@XQ zEstBHT`w<)+Re_4XfJW0oGXYIR(XHbXCZ9XFj2e^L$~KlUCcsX6MnCW89UA2e&qwR~0^$pG~$79UEoLDkeBk0mbTvww)}I;RNx zL|x_{D_5Q@j0zZ_E^?aoT3C;Q2Y7`|oEzLEEY?Jl9kx#cSdfw62EQwulFVt$vy$0` z*nfs?DhzC8$y-XFt@0;jDG|3E{Zht-ubrA-uk?I)5DqhNO2eX?#A9&57!<*c1dXGN(CNJ_Z2R~un}>9`cSa%{GqlELPCQk9 z!ZULIHul-#shAld%}wRINS3Vl&vB)jj)fuvFFXw=h$G&F<2g*fihNAnAK0dMD3&nh zO6H`MNBA!D^C~-WAQu@s5e>EkSybs8=i^@(K_|P4?&|idyH>EK3D1)ujQyKh~6~DQ+}#^!!-B3MC*`}`Aq@c?f19Nxm<)? zo=e8F92Oj8;s5p16v#0D!>1{K2KArwadZ6ryIgT`Sv55&V-E>)Q+qRWwudVvV<%f@ z;B$hPR4nXl;`TPKwsy``e4O0C2Mn54X29nHz-=}ebF0^uF2Khl&)LMRT%486oy6^J z9qjGQ?Odp!e`W8a>R@aNc}_PgQ*&u2W6y`*S^xP!gH6@d#KqIW{NWP{At7fMCv#(4 z^v6^_`p zA50xiD3qV8@9)xC_`U3dqy19q5{NQgQL69fk|LL~>8ztupf+V_Gs*<|LSHa<_VKAv zl2I^2QrOEb6%{>Xl0MOAHpH*EN2Mq9xa@(NHxL zQpROmfX-xW9BlK{a*Cy-q%h6h-6~jJU2VFfpi#61eZmfGNwt9d0%bxm&?S?xsBpKX zwY6hL-41xdxwU89IJOK^|Evf-qM&YMjs^4}uoabr2Sb`AHibyU4z>>*TVWbVUksZ6k-3o<(bQ6QSwKMNu?Jn#_cGWmA4+n8Nm6|WE2pmCC* zgHq*byJFFEx)HIA|Fs%{kwIW&B9U%1D(K1x>0i5?(+dBwUQbwIpJ7vq{^tgnMhF)r z2RL+je}C6_f4_{K8B|7Z{1o-g8+0vepeYaxL?XI~=cU|mYH8l9tE(y=9nAn&3PLFg z04^@1L8PLH6QU4gaPxNsc@!pWc--B6fnHJM?tXs~`wuPjfQu!KPyqHO1dx9L#&r!qk_34<3=l-hxNLQGb>*fSh$K6Wpp716iAG0c%s?a? zf?Wnc(#;ARlnO=g|BYIdaqyhzjv(R=k7$bvZcZk`NfvH5CbA$>(L>Y!tJ$$c!>D@y zwU}VBBNGKdmq6O{kZ!ARlhnc|;U-|woN0LmTRFFs)JOUcl!__sVh_w7} zCdeot5D}S(3b^uufC97}&}o6KI{zIug$&RcuOU71pUssh_DQM&05$Nib9HrHfGq0g z4bWC#DF=8`imqje4fI(A z*4sjRM?-meft8jl!(=Xi1+9oN34{gmpeW-YJw$8=04V4`ih4MNJV7M$z#v-bwFfNf z(nYy}p408|3S|u`=Zqo%fe0iD!2-&W9t14ozz2o^JAnlaOB9R%B@Pr4qd+v^(L_|C zhmw-gWRBI4OP{198JhosNm@y9A&q*SnbltRqI)o8Z5VriE)^_m!iVPxf z2*9LGU0nkrKHVIU{>c(tUk?$nQgk>rD#_Kz16qC*?Kq8+l8*oftbwb->|Kb8Vc7w& zkcuLSLX<2a|7;2Pi4Y)U>gtNqt*!TKR0|6E|E%(yxabJP2UPPifWB3wSrtO~(H=ku zynzWCfdK3ssDweGdUa@J1!z@*_44xa&HbD%Ite_`)KdQ4oQQxN3Q*(!bgChg87Ta52`EgeQ$qAnne7Zq^W_yNx*~EV+Od zePG$4?>tn~8ycVBW$VCCy3vYI>e6L!jJg;AB}$z)Dg!C?Au_Rx0(U^NU<9Z@ zr2>03h}h-}xw&~aqM3mQeuxS;iAEH$1z>t`5D2OMcnQRg9$W=#OzqPsg+Q-^uK9ls z7=aP~Sj>abJZ!Oy;SELe|HJyBNdV&i@(f_$5YU7`P$+c=*wFsqFSfR}5G}Lr5s4VY z_MqhlP|+|`XGpUuv08Zer`BnfTxSqDL*@=d&jGN3s2R$XOICW}4v+fn_1$vH<%!WJ zz)Ak){|~^3W_1JRZ_KbLihZuG05$ldLpa(K314hVbu}nuB%29@T5etI>)S6^{I2)^ zYI#7X05U)+qZ@+Uh=y%PB;^40e7YVerHn~n0W#483zaA#c$YiDl7R%7BO1zUKtLZl z2vl2bi0A;@wy^;ac#4K&0>&fC=>r)hAff;pz|gC!y0nansk~M3`Ul7WYDoU^`4Eve zt3gDfK}0~?LQ}!NfPz8=C>M|pg3lh@odjsCH-8)kQKP^bdGBw-`D-sSu}+c_+y9!- z@0xOCbmsjS4K7GakmV9wZIC2NFmay9VBcC5`ks07kH*!o+ zwp!CN*DB`jqiTpq?oK`>t5^@mmjBD6e z5BfL3l2R4q$|}5(XkuCXK0Ursu{319ndjqfGw(MIK}|fvOu`PBPv9L z$Qv4#yci&Gg+z2cw3T@M|CKF)Xn;ULqzqsP)Yu>LGtkCB>xYR(oOMGr1q=zqe|gOC zmvT{Z<(YpX8`NZ;s?;+VtYL5dE0X;c&VsNhQG%vLb7uc8W9sha<)-S&ZCJ|7ORX26 zK^aJ9050EtBK)PDZXY4H0tgMgFk)T6Ibev(e53ltu*UNWxG2WYsQVrrm8z>7-iB1o zlJo!p7uDE?1>g!aD4{cubkpt@ra`(B=X8+t8YH{}0l=!j4;o^3Ak>0HTJ&j`v$Ne7 z$bd{?djJ_EfDmZ$Al(o^z$BZDA{@Gad#@oW3=)?A!j4LEUa|>-jQwH$f;=Yx%>4!JFc6CYoF{VL3~>TtCXkc` zjRyfiP~U*0>Ta|@Tv50U`Ue(yx(ADaLMHN8A@krbR9yghKzIL_P^Q3nG_9_{IXkVu zUpMV1?WLmw6f?`;uziu+qtDz6-s1z!SYowQnC4|wSdwNO(#9}__AzHTRWu0%77il* zO*IYzI_1P)5sX;nDUjDo?r#uLXZ{13GDyz`b{!%><;&`UEjJKQirLQ~mBkJt(4l1@ zpg;;FNCC(X&;g3eyhub9lr8{S0H#2p>E?ihf`mU28G_yeDnZCC$eGu`>yhUK^R7Xl z!8Ha*^LIq7GD^UL*gTXlAt(?q{-O*Hv_LTq6vF}x=8ud$=ol$bty}>t0h}Dd49EgN z1BlW?ISSnklsb+GD1UKA6zIRffbT!h0~*U*AF|oswN27Tog|T|6QJ7vk6H#w97sU} z252Zx1t~B6?i)pYTBhdi?`{?|caAepB!4Z(P)Pv{fpQbt%N4lyf$pe~laBn*SMy0_ z{^^eK_tyX@cO4JmK?7nee`-Xai5~;y>i?t*#A1w-P>+C62S5Wj0<=N`pz-nmN>(h{ z5GQRs%%_QgO8cVg}`t`z;W{LK4s)L^cS31$Z5QR)kcL zDAdaTq6>sM5Zh-*fpCL}ZpF|PxJ2`==jA6B9%2_zIfK^rSl||b zEC5Q-6{-e*nG2L0@W@b~d2kybI&>jo_4y#iQOd*wK|p!fKuZ6UK-x8clMr`-$Wkf< z+=n$7pv>-@`}?;(U4-AgkEOk~B>|$OS%Ut0Kq2_eE>I8v3;_l>7>HyzMiHlM|0-Ef zI_~dpHSg~pDpW|#2N~Oel&!hJ5U6Z{e*!6%)2xb+W1tXO-9xLOKo>}y1qMo>u&hA} zBQ@Byc_9A&cfJ5#{|_!uoeMTS3pIwNH40;dW^AzZ4 z-QLhjADY8}ThYbPyMGM{U_GyYs&0S{fRZoWE#U)cSg_%J`TffM&5f1Sn-j@1NO=dO zQ~t^B*IyTa#(z+Kh-q=g()>k=jcns5fB2A+*z6(BaWq<}})WG$OQ2gqX#j{{N7D0o(Xj|CeR>6RcA3 z06IZdLp;DEpvoVD0(5(b3H-^rf0#hm0jbQ-pcwSqpy5Z0T*CoP3NZp`ngy;N90HPf z|LkqJgLZfqNV}@$rb~%9Lk3DTOMSikXE1p#7`4bAO-ROvv z$T5H9cRALI>d^20ey`(~ivyT3>!IWOaE|oP0Rx-j5GAU*cEOE?fDC=EKY>aCIS|bU zIxvHBpEJJ(=nzDPa4+_Lt>gd!7ZRxeIr`fp0J(VxRDXN--*N?Xd)-xI zM}X{)+MzxCKaAn8$|Dfy`cJ}*z{YTxQ>ON&_gBC@AY2{J#R@9@-SUw70y>=dpROPQ z{86|uH_@y65a3l z1ZoA>h7VR?cm@V~zZP^*YOP}#l9C=k{Hx&+7YrXF6Dw~Kbc_r_27;BftiLG$39C?j z2O`nm{htGpmVgo62R(YoRgM1-YwsS=WZnJ&KjEC4ZaTmNhtvs(nwe7&eLONn0Rgo< zCK=2$nKGn)Af_QP<|Hj8(LCS*6VOy-7EXhdV4B)fNsvNJMCv(!$id{GAiLks^}RR5 zdV1bJ-WTRTV7u@8`d-J+_4!^m`F~`x?+>zBz_Rrn1CgjMgqsIaOF1mdjGkEmei72r z>eJfxB;p?l_~q4c7wQXCCUPTP{sl$CFq?mYcR{Mux31MuqaV~5t3hCp*l@&CrlWxOd1KAS>6}VMW6s^te5T8*dg! zc~}=U0$e;Q+TsxI0-QAOWhU0Y{?lfr=^R7qPxtFAFznsR0I&Mf>l&a7>|t~43A~dz zYI({7kr4V(eYWoFOx0fD2dpCKo}VJ*vI35rI`3?({s@Z^*Xikk3NBzqHIp|)o>r{8 z`pO+h*;YvNKPbSNL8E`B?mdL@WicK ziczRB#?aSWcJ5vJ zZm}u*=6;sWrIxl19*}>G$U2bl@XNJX2iG1Pcbt_4c&+`=Mn28y+3cErhv6lCOw;<^ zLv}-WahGQ?FhIlV)al28B?(3bGG$)1MV3}X`jV)$6DNF=JFPCSa^jM`7N54NR$xh- zCJ9Hwd(*FEUjO>P(i(EMMB}BK7_i z=U%*}o-V)4z=EESgS2ySO`~seyTHHR>KzgX{dD)W7plMe(S*iOBN|ByOd?Mg@_vpH zp5OoGoVC*Hhkw8K_05R~{!KrmM|}Z@L8bezSH~~y+LJIjnQ886$^}^Pq5Xr~7Q_x_B?(rZa zE5bf3S2-2{G-T=0PT86l9_DPMYoHlKGG)r@oitt9 ze&Ip^*Qr($E)+V%yizigPtfW4Eek8EoS?V#*21J&+S>7yo1}(*GF5%-HbdZlFZrqc z5UqRhY$$M-*8c7o$+WhynIspLmIM9q0cK2@At5fdyb#Gj@I(-XPG2G@Octpa#{uQTXXf?7-#VK%G zW|^sfCDr2MTEH3rAw)ofqCVQKLEquoXP?-6$-nYWg4MH~We+^dS?t7qPqFseR zkf#a4w0v0PbHb}ems6+iwzQo()ne6oX2l-P|4xF^*dC_HQtrH&Tikh~9Z1nyQ(&HE zG(i-jLm}!5arya{(Ye+39rGG3+9=29G+lG;v|a&|mB9QNh)1SWt~#RWGC3yjs*E^D z8odpQ(ghpSuBl{s6M!E5nQXtCd>uAGlK;2|?Ldc5ptu4o9p5C|#o zr}UOuAQbmKU7&$B>87fkdj$J%^;7*9b1exM@NsFvyif754~>_zZE;&JL??GvcEooY z&^RHbReSxak$-o^d0EnE*_vEx<|qMyrl+ZZ2H3J5w!9Tna?@--a#$W#A30_#sWF|w z$aPXxHhpZ>m@>NyS!6#He=`tG1X6L`ZjGnKiOQ&H_+YJak~2`}N+0t|o39{$(WS{G zZcTls&dej6fI-m*))htGTP4)HO7#q}Ata`ReMhCw?%bT(bh3E%DBhf(i|>9871Phq zAgQ9_g(Vr?JV!Sr#&T>lnly`--fvmF0No<3gio$r#QdeoZ`O3f@--I{noEaWnY2w- zzqBb;vQw+n7hG<;d*ldk`?AK%=E$gqPV`ap^A(A9@_UIrCOi)CN$IM?X#whF0a+wV|wb<+%XRX`T!~Y=8#wEWt6-3V0c| zIQS+>tg!w6n07&-XQVLJT_-xSiHCnmOG}H80qxfj^mSD@>ibjXNMsnk-TTW|tl$gp z;m3(ie3GPc+WFtqKhZ4RCWtAtwUjBkpvpLi>2O{``R;rU+Hds(P7 z%$vc^nAgyI=Hr1d z^g?q&$GS+#!7~B)C&idG`e$qlh8h2%^{)cb^qd<~Dbgl6zwn%SFzW!~0(Xx@@a2U= zdF!YrD``Umn*0hJ6QCBZaL~OS=t6a^z&#{5E9A3F=;>!5l?8&Zfv(bR96rL()&deM zBE-)`U<(QUJ>5<3o8HuijB3Ct#l>wnws?60CaGKq$*4sSSY6k4_m@x8G-&7CKlOQK zC5M*2H5XzT(SFvgDpwj(B0VZiDg$dIv#zo=vf7%eHZBJ7W8AC0`=W%=FaWWUIdn4! z*S-xb^-kq~MdTRzn`hh@a{rwF&J<#bfDD6-3MteTPxAXC$IUY%0z796l$>|_bawIQ z{#$1A81Bh5^1s_bpZSL+o2k)1uXGWbB2Z`QJDxgKr(2^|lKf{s?zRHttp)|S)!Mz1 zzT>3ZQ~UTKfo2jP+QOBUMeZm45_FEz%SGj(;$@J!8o=+F34ntU+9JoC))*^nT%{0A zScZj%7NgPvSqTI-40_0=8skJ}5O?f{nj1^^g;aO%L$Us$ST9o^DUS4Tom>6K6$!C2 zs=&)gw7Y`+d2N@1UrFr zrT9pILNe7`DoCf5_HA)ibJ!muJg8B2L*4hjN>&7TD4&gliT%q$ z`>Ex>@~9|$)-#tyPV2DI97)_4KKIA7l4{mxpIe=LK5`XZiJYnU?D<97AM80xzD8px zU+u(Gl&rM?Sbvm6d3kFk-ZEACkr;sU1)S!>CZ67xO)k8kXlyzK$L@<%;$CfCq!Lk{ zau62rtXWlAdH>X@3mYhbdUG_tNIW%$tft7+N2PI@<)pd5Vn@B=RCZ=&W`&u@e*Z{W za(~9h>Gryg=dsYU6s;wDTjAJx- zeSK4+(lkahqWCkO*dLZ9p`*25_dw#~f9@Pv%yoxgXx6{Xu@eQ7<%QTd94->qAz9PfIeRbNTBp z^{PR;yHZ$NOPvEy$fnAhP&G<%k_JW~v!+?kg_ZHjT+68^f__q6DWCY3+scc9*;vJ{ zt`@Q^XV7AQwlAGLcK)q5B}qrQPVT9XS(8VUp!?hED$n_)jQh(~2qs=dqJ5o}k5p}6 zCfd~=(C~tuIj-j!W55i&44{q8bwW}kwZ@d!TtdNL+49w$!s{*Ms{hRD!?|2wv1M0d zRmqfMMOPU}-yqaK3oH%QhEkSG`R=HtDhJU7WJ^JbW^_>VC*|L)a8)tc(gF@Opyx=6e}Yx+Crg+nMiO4iqU<@aOxE;T=&(OnTsG&_1%d&StpOL$iV;$6R z-v`%{SCuY%KPIHGJCm}j`?x=ZNPCwm?@$~*Rf*)aIOM7Ol&O8;r=MR2M%-J5t2UI! zE(SX+f3Z?4Qh?Xyd|cwv9ytz|$fyh5sYpH>*5E2H@Qha?EXWIWNy0uzytedu7EQW` z5@SQX-o(hq4FOZH||z(#GP*9%yUsDDQSwUhIH%1W_x z@fNaW7bs_o?sk?> zSs7j^I9dIlzKK21o!r#}#3WE;%75FwJ!R^^&k%WHUkzU9njb=4oxU>V;TME4f_C+d z!U}cP=O>WmM&CRR)8h#is^^Inz2I=rA^x56d(*&Y>^+&^`<{+ipt%hV)r=#y!Ifx- zJzGg5KdRTLp3y3wHc;O%(vvTRt zj+-mQI0K`3q>^!tL6xNSAi7ILu?wGPJx%G?7LO%I^?E1< zVM?aZ=ui$FxFi2AI%!m?T2WnDc?XS}o+_=Oa265t_^xn>MWXM;QDf}4o#Q{af`;(5 z7Z>)wK19%LEQf$MqFsBi;u5RDRK%RbRwtkte5a&a;Mf+j z5J$%Y+>~O!EerSjQ_<|Wt-c#gKUcP4qbpyS{Pc?_txP=EVceTgceH28hM`iT=vjjZ zz=ZKryHUdpshq|*n6^yJZbnmyy7>2-n=4=Uom|ykw?d;?f9deG%iM~X?|w!?S!32D zfi8(CK?Ed5bfLyQ`-v*!y9Ed4ma2Uudf68pt+YDGWm)m9)aY z6kxY#GS795M&BWNL(0eBdF`F?dtjm2xw}>sQI+ z1Ffq&jFljW11A?VI8(GMdHhRXOjxz{`mccCgMvcm-2$WXYv*3^YBh=hmBFkz{te^2 zZtcESlnQ%2u%9yg^{FFXAMJVQ@XmdddIO2zxvs>A#{Ykuv>o0NZxYqe_!e1_CowHR zr({cYP(-M*yxcdj`J9biv9SL?cJ#kGzL)mXPtD{)&PkZFL$lLrOsh6H`6lXRa_|dp z>BP5lyEtMIeM^HCEW&7#K+_Y%S{u#?G{nFG^*1Qe9P~f(F&MQqBQrLjEf>myd3u_1 zQyH~`=HA8!;w^J>pB!3-H8Y;1Q~*n+VOA9~fdH`)*%IC6bfD_zWE!7l<~5 zpkfKSLI4k9njcN7^em60>(*a^A?=8UpX)|_Wxj7_-8%J($X5%Dtck}%`C#zd$|X_p z;N1O4Q8u7Cjh3jDDK;ueki$K7z7_^I2R}FIBsNKac4?p1qwsa!jH-D*$M-N`Q7d3) zXUAk(Er_T?NA5Z|!v$+DS~(fkjBUSVbXj`I9~t_Wt z!+pwJP<_wqsb#^_C~3cuBx&c88^g%S8!E_RPHYCduj~Zc71(aX0zGSCpm{cJ^0eeN zD{s&?HK)}P=A5{=GHzXliEshJ&8ZG$q$QW&39FpS%R1(n!E3d@2jL$A17VjHu7NtU z+74nb&8YEwU)~X5RvB<~^QyJ5%9VToA+OV+$GAC?oE8hCFTRr08nW^b%wg zaTSb*U0@CvpOy5IO1P*uooVQC$k};Y-xm=RTs1za-o0q80R|pYBu!EY zql-10aLq^=`Tm0BQFky`GD~IJ*0-VIVd1XM-QRz@>dWCDrru;#{TXlMIJAY2a<>Hp z)}HYyknU`#r{pCmM2IVtD0|3!ugJiIXtx&kUCIwckbd-kU-X#5!b7>n2!F$vk@@oc zPi@4Q4~j-ax@~asOZT2<@@qs8hyQiH#=;kJ2nTYM?4e46lLumuuVxKb7gt2`QAtR3 z(-U(=t|E|)eIHx5r@X|ohkbmT$}+8S9DOS%o%6tzB>c(Klsb`<%1-Fy`|&d0qv*I= z3q)@hDQI3JRQh-)cwdd-SphF&x~kyo4!7x_3>DiqS)Y*cGG`>ht4DAhQ5RN6&q!yS zdC=n8R*XsD8rNS09=rvFvB5Rw;$uG8Me+G^axt#3#o+OM9)%FiH><8b9pc8$99ETi z13~QSK^6P2ti|f0j%>N{!tut=SSx`8ZrX=1Lafn9EG;eCib}d-Xv&n}qj*<5f_N%N zH#^}OtB$lPlvti)Yl48l*n0o?qEBJ^#2`8&?k~asbSW62tg`YKNu)Il*ni>P%9Z61 zIS;kotFN*=DtOJ`no8nu7@U#Rz>q~`N1uGJ?^OwoIT%S+xnoVxmd!e-8qLlJl@|Si z?LuAYh^-S>snig8#<)#)aIdyLLFV%0cC^3)cGYv8kh+G6y&{Ei};Ys0+q6HNXvc)H&HGzR8c3j8iYQb8qBYE7x;LgE%u}EAZ#Ii_cLCe!BbdIm-X(tx2IF zW9`@!74|rwI27$-gsW~!jqKKH(Z#qv-lSW&uTy(+ZGTqk(S4{Pfe6p*5Z*fEwg0>; zaIbG`V|5{;7EwQl0sz0OTVr&Uc-5F-zg-Me+O9B3WruR@f%Y+3Ly4oD$mt|Izqdm5r3`5R&oBJSUt^`!hb1&{0f5qqU05t;gPi z2oLN!x^Dj&8sb0Q-3e(v*L3CCE7mRo`r)LKOxq5kSBRPbix4F*(3zf*n-~WD2cpM@ z33wH(83?&W^`cLZR%{Hq(~5r5jF(4{LV49JS${j*q?mObmx zq(-N~C(*?YOedXaM&PAO99I`Kmzb#7u^Sg%O*!8=*5F{+p{xJr>An>LiP9xkG<}rO z^qk-K^lkd?-(*O5Sw8vx$?14fou+ch>+cd-(VL*~ktN|F=8Yqi5+bv-u>;H^idct) zJ=ANWKq_M7;I97cG<3+jE!LEuj21QVXzgvvne00?^lG6B-4fQz{lkMu#daZ}BC^=F6OUvkB`V=tyNTVV>%AXzIXy)2MEGvoJ#XaeJ`|@7UQMnar>{kEQta-e8 zEgX!=*71h(|8=j?;i|A3wT$l$Im$Oi%-Yt}@BnmEkUlgs8f&*#NSWIf(*`6LrQylk zdf0bE9ap!L?Ra|5>452heNZ;1v&pAUbMA=f{XQp{`goVJZDkA<^i8(ZnQ`*qDe)NE zbDWxCbhoUV+diE#J^UbK}-jU2l7gw4r^ZYe5Z6u zR-DzWblGhk1sx+6HP`x}Y{YVAZjLQCo2xi%7RAn*aF zBq_*{21moZ%}8W_iv1x+dK7NHRMrY_3OBFRxnQ_KXrO*?=9XOpYFLT``Uawyvf5A; z`_DRZqad&nH!RqjlHK)DpXD*WBwRgF_ZVriyTCy#Y8+^;`gxEFRs{GTS1xqw_Ha2@ zgdBu;*Q{&IZ>_Oq&{3}a&X@GL5VyhNu*%>GNB`mOD>qh3jx5vt-yfA35XPxaQAWIuTb_AofS2`NI6iR`&|KFvB8csEW;;)7= zaU!z5E<0Fr@rU=$PHr(|V=fCeJj0>R63?3JvV`b<*(c(RduDPSDmr5qVedli7t4Pc zvrrg2QV~>^0j^)(CNK*yg$VF{->+jwnD6*Gq1(j~+LEeiaGOub9bl;3ZpMb%vcU7} z*C&A5S`XwRZ$6j~%a?rm>4gi%V;2&(i1JV$M@~HX^@u=(#M-7u@dYhD}@d^6nD7R zc-PIH;U}8P+_IKV5@v;%K?7ppd+E0L2+v)4p&m09IzqfT>aWz+))7z{cIlF#TvNcZ zfwlWMPJ}ff7Z2B+vU;WDjB;fymCAe0GQ3qd{xmNyNTylkVW zmPby+ehA~s3cMTJo(Xc^bL_m4NT>>smIDmNVQjRespW$MX>P6YD}5(hPx zkV|Vyxrp2DkQ7lG$7OIaSlw7;NwJC#XR$?;q+jGf4n z8q2+E!oPP;Qb2(4bDACM$;+2_Y)&YDj+wqc*z@KKos}jy8YGsLzr+&k0zf4<$I6gq zrd$K(Mc@Yh$fVjKf%SFy+8jaHo-U~}#e<#s?#Q4gB5*G5Ct|UKK{rK#KA1G%qs49l{i0GdQsFBY zt`Ca))Kc3ge%_~{F)pD~kh*#E=Jw@b^VhG(Sb~z6+}!hJmJXH>Q_X@a)|@u04xY$D{3?{AgwPZU zQcLT(%(4l~$oXP;(GkXOtg&t)K#Idlo-XjJU1I^)QsXw`Pszv8o@x0PNsc(_a=G>z zgDHmw)lUGwww~fzNnbiU6j2wWwShTYaSahgscB%XRH(q@)Ig*3 zib4K@ASl5gj$04nl?@i4Z!kwHLVi;vEW#KRsw_yR(4%nz8C-HnGlL{&u}H?6`k_m1 z-^SJivefd(DY!hPT_4V3>7t4tw^TyF72GYvwk~=>1Ijb@R_1uK&~RWHtT46?OQ}FM69xQ!L4oaChaTWPl?=W z!OGoHNS?9kX`M&+ojulq1W;5UkK)B>(q9cZF zz>6AdJ@yG!EN(R#b4rGpZ3SGewYn(T1krvLNJ)_o{umFOn#l8ZSy1QYc7QRAv4Fs7 zeSnaN$bj)Fsdi&&o?hmw6^(6WaCgmE9{PP=&Lz2LJov&Agx!W}0bXEx%aZk9 z{V-Otz{bz*5;{a4mDJ@rr20g8fTMciiiFFSqGhkp<}N;kPDe>sr1E*c|5?6t)fkKA ziGl^Iwlcqtto;3Py>~9gRZvK%r^R&;3leQok!DmaSdW<*0KEIGLn+4^5h`l>TxH>yid>~UC6KlZiah5f z@-xI7g%Kv8c7`&0Zs3hP+z%6J!421$(5k|&f1FnGSNgO1YW2TBn zgtZnUtW?L^JR8_$BsGJ&MdP(f0lyIgDHvQs{TP1d8M}CNLC_1@;lSJv4zTv9Y^+`I4>u}nCM&<_gOE%5V~+F|+xez=#Jf!Y zn5dwXU>A*hvE#Y?+J|kY8L*9`7et9D}nEzS)o9RJwodF%kXMKnUq zI^0e@Yc9Ce*vd6$VLtUMAj8V*wF0eDz8g5vB}Ct`2mWfvox+BOXprqffO2gg%n;Ie zwpzy9N4biv$K;RPjoFZ!76qGt5Aw#^5idM0Uz zEO6Sy3zkp!DeWIEd!LaKu@T2gN*tkMB`=Fg)m1qaXCt#2u4@6;EWT8FrUMYbmcKw}R6HKw1SDLnyT0})cOgzE^ED*G z5CsD$**W@9qID1B3OE=TYg6Lw7Az~22Y8?k$e9}#ZsoT9VF)T4=A_1&Dxk||lDe`d ziQPef;ff`qotN#0w)w9S@H4jt-oD+9X2nmcGki3P@^5ktaNEn__uQ%|oG@RR^LxGf zC8dc46*eG-QQri$ljqMz`O2Rst{D!u4=J`to)-FMfu$qeckAHfp4}$N5O}sf0y{#5 zo0SGE4|(ZI?9M$VHL_E+7)6R6ayIf#ZlbQo2YeF1pPz z@qJLZH|etY>}0Sm{t#%atb`Kxdh05Y1IAT|a2B?WBeKSzrO{_=zp`2LDpUe z4hZw`a1dxEv=d#Nnojd7!K!rfn&UKK*Su&4P^$SsgT#=dX|{k$r0@xfa`N3C(6|0{ z+H$-B>JJf^nvUIBrN%hh$N_|&?hz;QV^5H98XnMTYdxp3FE(6}|Jq(MeNfO`fC@m# zF!F9`9HA3FuDDjEU?6|JerKGp0l{q}9!`Eu3VJ*$k(^Mb1Wl^(+DR)IDNnN&;=+YG zeq^K_@>6PJHz2HQm6LIJk^Gb72<%FhYwSS(VNdTbT4;|J{ugl(Y`4tSO_5E!&#qt>c{Q`2Z(GiaZm~y3q(8=dz}@P=VOWh z>nj#8dJg8Ig;D-+q?lkd>l9pmJ~8|y&n-i$0{QY;#MmH0=FJwwB9x%c*9KB7Vx_I4 zw2O(V+fTW3r5P!-dMm&c>j)#c#| zfxm6g-IjN*S}EF(*_>Mm9lK6Cz z$fuYT$&QAM8P`Km>6T_fBdcCySdpnB&)E8GOLO43sv_&) z#)&WWgs4I9=w8X>7d+-=pp-*wcu4~H5R}K*T$7X^9tqWy00PLKuVSJiYofJC;F@WH zX%8xm@0$I$k9A4i*20yXI#v)%9N-~Sj>8!VWMSOXPgi|AaMX615Vd`~HOoF==Z%P+ ztYl__Q%|9@u+w;#HkaNn-$aXW5R4{7sWje7Cii}E7;h%NS~3=#jhd^=h%iU}apv%o z{cfUNs58(+K>LQJTjmY@XIc+LX5!(<*E&DgJ$0K=EAVe+%|M05ugFaDj?(-&C%@7=rzNcOdZih$oLKuelFaK+Z+UI0i`g2 zjeSrFD!hp3$Uls1=?rY)97OW{(0Q#m=5AHOy3F=X?uYfGt&FPuHpA8>*$W zVxj$u$u%eYJ87R5FIXuW|8jiBr!=5aOp60#GVQ2q^pT{DT7))|q3!h~_|M=Zw4%ew ztN)&+@Ov=yKcYgr;o(Ii-a4~z6APx#P1&0#;)^@eMP?OO=o;wty_sRj6MIPHzIgZb z%_3J{j8p1$e&n1{AAh`a5;jY0U&)$F0S^FbkV<0R=;1)m5TQ?E59yHfGQ>GWqKhGM z#+!WmqF8;@HN?B#h?=tqLdUi8hSZb&=aUQ*1&y)j=j!+U_2}>e``seEU4r4|;Tt`m zoFp=Oq!kAWwCPF2a}lg~he#J;BYF-&7M;0{80Dc$irpTsQcNPM^3M7pub?2ZLy}5s zPnXRbwQ^x;MjeJ$hYgKMqM>}4FUn}!72=B_rSBT>+uBfwT+%+cIKV;dffbi2J@{)k z?!8r3dO8O)E{pwQF_!}$RI$IlO;!|)gdWEDkew)HfONhq@iHw7d;1=M78~}@@iSLq zL^yfy4ayRb0!@KT|uhp#j%q zb5J-CGsIV>oIPKD;?43k|Ni2e?}gD`iH9Wj))a}9g>*b89KsjpM5l(gw4bQLWx=6- zyi56X=`CXc=iRFwp4?ELo)SRkPS14N@|2JXO-HLb3b-E=qs{qWGewXm(tF^yyhLZ` zsk6>itZS}KusGeQLkv~n#c|g^*hsZhAsw1sI{VUpL4XHBhUL~$ z?)Nheu8^XHNsnHL9EG>HJ{;Gwn0sO;Y_lc{B%1(UGGyIal=&QoTFvw|$&_6te;8J& zIHLB+I=X&Q0e7?q4nS}HOdJB)Y!nyxS;&l`VVJjBh!WROMDO2q9*CJZ6LoqrVh2*R z&b+{}T!+SZ2dD@xgq;ii7XF@;4gHe)IbWm_4wTao#Btl=qIeyK(AYaF1y}JJ0p>{7 zmB%;)aTX_7r^+f7(pIuC3R}va>%jlHaN&+DBV!=?R{YD^a|#KV$&sa1NWs(-&Hazv z@p1B{OJT|rK&#cC)@tnf^>8dDk9WHEt!DN>N3p%zj*U2!Z(0zaRzLdro#RY(dQ5Wu z=KB@KVeBaQb6i6r`+f->*6(9$r-gR*V^RudG4sn#`Xy%X?TPhs=uJhJur}8*0}5b{ z

    !dO*kUHps|GD#SOCFyv-ZgqL2X+2Z#?^*(L`FE+Nmbg~{)mwDV+zUtigWd~lq zu@Wuh|Fl_Lr8*`D{ygd85%1Ygh#m@pkaaiGwI{9i3C3#nXE-t*0C6BhdWFahEYN!0 zymG$>iVuAw4(mUxLe$pbFhMv8Rg_lgs3|2XvCV14(1( zmvcu#sM;7fK`Vp>)7Zvqvu`5aDY=Fo?2qkmXjJ~JA%RpM86RCOM4x!CNft01aX>s; z9hOj+gTAEoTt3{zjK_nH#3$^eSsQoGk`JY`q=)B{#|r{H`qO_32$-rZXztRci=%p{>gcWDG4klOOdNv-m!YYCd71NZh4VK*3g0tv1}975 zMFzARD@fn>%PkG-JhA%GDQ@^kb{xD$;E&_NQs_O<4`?u6N%-!Pf?X<|@k{UHYVF5W zG7=)}L|!kXay9Evqrh7?+>fB`c&3+H>l z#0{%el*st=Q}%3pk@UxdPQ@2ZY}~`fwtWbS-lmgMiv` zZD&0C4t+|^33e%XcAJ4ef&R|Uru{!{;lVe*aZQVv?*MXpV_@iS!NP=p@E29-aY5?Sfk1g4aN-GW4U3PT^r+eqz%MFOO12pzDz zTjw<-0PWWLPI=0LG}3W9;kz&N_%uk`J z9+N&x64(zLPRud375dC@u1IQ7>W0=6mPSN0-Z||nDB|r$o~TG+pg9$$z|AoQFkw_B z{um_&uVjgWOVA)(C;hiK2v9L;fq78{T)JQMo40TMjHRGQVsyo0U;5Vb0sVJ3&>U>* z;vNU4{GyeC_QC%Zp8evdoG)T0f#L?s$TKHUkM2wU=fJOefojU$56_3>Dm~^0v%pGA z($n%OBH{(h)+@8^$j|p4=;jVl2K0v|c^o;qzVnp=feWsRa)=f9d-*YW3Nol8M`M2v zpYxHyeZY^`#wXzg%8jIj>i$k1sljyfk4^3Ag*s*^q z^|(G{)bb^JZ|Rx7&`S0!LST@SUz^#Cv#`7dC%?ABSctCiEL=78y5~KuK$KD#_`NJJ z>u4L-f$_$SXS!=8mcATU0;$LXRFL0D91(}HEX*nb{y@-xd_$LeVo8i(o)cbx$)}>7 zDb`yBU_KRGafkqq>r7C~@Cs!#YHqHPYf7bVGG=~BoK})V_y>%H z-W7skf9qq+3#)HyTpU8ZJQwv|6}+ZL|B(xhp%nMnt@J|>#a?P8K`}?Kud<8m?}W93 z>!1ubfW4*iC9xozPfzJ|zyT9P#*TYSc z&i|GV3ixZ0{jl9Vy%b7^0dQN{8K$`<1*Q217Ev}~JADyLJ(P|cAwEY+eLPSTL3~9a z+|viQgcABYyb=HBxJ>q)fxfV6h50bvlgUkC7N(O-aJKhPWA(S|en@!Ysg+nOD3izt)o*yQK9usdD&^S zu=kC%2dq>(Zg=~SPwsxYN6i=Th3R+&T{}cW3v3TN^nmHMd&l?SnRXF{hL8MhgGE7` zghNPGzkcsu%(*>V1-b8sl9W{&pJ+uX=nMXlc1Io*50~Z0J^2cdzDZKqgieu?oj3g? zSe_KYs9VG&9cu|-eMWEzeH;QjC^+Gk4j_I&PT4srQys$>o^u!J zd-tXWtqjmW0V`aJw>6-L%=xrIXjZfw79n z+|#yq2|~A9paneX=?E4*l0>QSB&Nt?H_zi>PddDBu}vb@^Xd;*$Z`E?K+-1BE+q|> zKU`x!bT;O1W87Y7D2*fWN5m%3|Czoj!c#n`JG$VKcWKz3gFHgdYl-+0pSClkJy#Z~ z$Msy`(+9jCZzlYnLe@BXbR+*u^J;dZYuclN&~ zJ=)>4T#7xO7`|5@IYb+^Tl(-HvE#g3PCpKBi=XkYyz4vX^d3Er6G{~y7nW>)>NHX5 zBaUqfZ$30_c$2Bbc+1@_>0htSxK~)Kxi1F=_<&+Y+aoxt6NtNytdc0>`$c9-p1JoC^{Z zZYnw5UM;_zx479*-Exc@kYAs+JE$qFJ+>-!sHNs%P*7y%X2xYaac8|L+f6(DZZ>F%#zKOZ$2froH}1ykXbL^`}45*=PtK=HFy2y#>Rs6 zmW~d5xoqj+suJR#L}fW$mfWeT&Y$8csP(Dk3~x7a>-Fue`~DHVI;_*>yIxi6Gmcg@ z=Nd~oUp?aAd}&j%a$-GK(!M2k?@K}IcW&p!#}Aq|y6)hZn4|5V|KO4Ban|8<;n=w* z!62>d=-ew~T?2*>2rQCaTHZ%J340j^{5-oQzV83NR1DwxM0IqQKKw`Lr0Lrvh4?nU zuXFR?udmWq_AYK8aIAUsYq`_6df?{oBUY8BYSo4IPZmmMA{IBhpc+IkpLU7j&ZR6W zcReAqdQb`!!-@e9N~+eKai0<@`tf$rl59-03KcImiI@M9G6#jsG4ET3#2(nST7>PZ zeUc^&8Iq))j5|=GYZzD}EzNK}5im_yTV=776LrbBuL?tZ(AEW26i!c!v_@b8<(U;| zU`Z@GjqWven$bCxE=8}E;_v0V6>rwYbY?c}E6C_5>i`E8`+#sSflwZ1qI&_lsxjd> ztQ8y8F=zn)q}Zz)LjN#7ZLsj2QkDG2$&tggm8u)=7WWi z_(U#gpXjO%aJ3aPN`3=J#rgV?iLi)QmX`!!;(Px zr*2Xe7uw%04Gp!_oh?`q={{u%#F(wijzoEd);)x3Ts5qMx?HD%mtGsXoWxcsEQygt z9hO&4p0CWsmubBc8ZTR3I$cu3Xo%ExW9@OZa5IER+~-^jg7tydOUInom+ zOr%GJ(cwIxXir)^T{eark6y}XX(;UIUVXeAx2h|j&Ma2uNfs8bJdzYs3mARAGH;_Y zZxa#gt-|8R^4&lES=+b}Oto_CU#=P#qED0hIQdoYc6~e9NxnKlJwRqD>;b;?J5wq z(CL*0d!s3jOWcn>mGWqjDx=bpcjEqO&Kz{2`Do0g&JitbZCrjMciXw%2b&Hmlt)TI zqFj^Tx)@Ttev`CpnVj8iXuECLe!tVFPq&wo zl+@cJz4@nzi>tH-jMTyH4P2mBfhCtaEF>dP>{VdqWI57Sk0N!(0VQ30{6=0r7%6oR zV^!%3F`o))1FKDVzFBje%j45}m^Q!J7Fe=HGz7N9coVc&4?Go8j2Su;HpzjvEcx82 z?rbWyaGYtrCiXEpXkf`kd{IF!F#q$seo+2bC9V7EnlnsF1vd{|RrNHeA~XWqX>heM zNkxNH+A*dk>=YL5ECQQ>4cSt8TChksXHrW#E)9bBPE#sMFfttnHcC9MAukRXKZVCl z9tuMqmzSTUPxe$^e%$v)PgvzfHjtBzh`K)Ww^DIB?$Cxk!b#YU6!NzE9>zj!W*Er> z?|D72m5XjRlLdoQXyMav@1MeMM#r357=+_ppGO@DUiZXSJ|oqq0qKY^y{T zp;+Lz0ekF5!*R{icEEtaP$Hdu(fS>UQ%bHfO}xzGT1-d(t1l838inx~wqlJ&mTc&lv@M#q^vId4y4teV`FLo0Ray#1{kS9zwGHAd!ehL^GNp=)G#$jiVdWJ1(~c);53f zdpz^QFlpYfRp~I8$F_j({MyTPJF_z?mKe`8Tgu48tXE~Ot$;(-?>(I<@u)EMspM>k ztjM!DF9_Ge@&&APF?6XySz9x8*aqy|NuS-O!%duIF=;KDS7eCet0zYy7O?yF28=&M z$G843DAL2!lq&gMaxEC2b51%)%HHs=fB5FL`u4k3^_HquY&!W>_7>e~(P7mwOgjv3 zKeJFH#I3=sLNgSNkfbc~QYOp8`7yKmbxvFa+^`NFc|TmUbjJJkqpd7u-F)%dkbk{i zXAM~0yz(HMbAA@h{IdU^taw{qnC~w=F8e82<>X_ZH>X#fJ^?YCWk7JUe-LC^eC(~6 zO3*0LL%Qjkq+X?P4?+Ytq^?tW-XgU@K!?2;3_qNnSBh@KB}U95XVLSh-Gu7gBYgUW zFH?~`Kw~nRk{bBUymsz}kE*wZ<92)^`xqbta6Dg38kZJp#z|N$w7d6V&b)jsZg+)2 z5A2q%Gxvd)c+yQEh_H_z>pH-703P_HC+8Q(D^oB+2`-$%+s>C5fKs9m#9ZBgd=A@5 z4@$j@)#*PYm*RK)4miEGGWNP`{0C`=tD9W7p`4tsmwAqwk>K17i}30n}`2Jqal}!UwJ4R?p%vp zl!f6D7=w)b5_`}UffqKV$S0h~eTt9cb3el0ugBk7`Ed`A0hp0UyK|wgx}m?zyzbuS z6DSDIMKytL$A%jq;pRNEp3D<0nM6q@IdtUlxZ4^)2sk(zJz{&>!F6)0U-*oJQ**8W z$?ut0qtyMAJ$Ub9-lYpaP~O0WNco$8|DZglfaOtqw#ib?L6Vduh-_>a(b^-2niOH< zS}*+g9Xb7WwGO6RJhvp}W^Ha-;N?LS;*d6xm@fa7f(75uq-1g(Yeo7Vm!{2FftxO- z!Xx)ChiZtCg^t0FA_GjOf>PQHlR&=v{Q1>GdzC~T4n4yqv$etOsd}TwDBM}C8m9wM>rH}K2Va8&LNa!)9V3?i%?f^$0=bLKKeAYh>75gCe zvW$$6j+i)gUZba3+E6>TQ5m}@oHy;S@fs{#VJ8{-_*vr4N6jK>>1|$wd^YOAI89n{ zlEAUo*-cx*7 zP}n^OWtr)p6V%@?(~SCgv%)n_`j2Lb3Jo7u{ZG%AP_~$EnSqD5Of$BXbcv6Q6d*|; z%ig|y_=NhGIgty96d=_(MvSdS2151bCIpal+=~=5S0;<5Z@9P7$WOCDjtbI%8*abt zs*jGLo%e%Q;N~Tio;cEtdNE%RzL9PT)%KDog>9&Lm1Xj=-OmovY0^xfP` zd2KoI1yxVlHlvf5gfs-s?#eJYx~L;ZE>33cbL4G5c}aNZwy-jK?2D|~^`vmhcF+u({KXkICI zb{dNg&3u`TFJ${0XSI=ATjDf_#-Sj?@2vdaiG3S%5_K~+4b3?`VeuOeM#7hoU;B)n z$glmaO}hvWW*rhK?4y95s4~~BiTNpA<#_H<_NRyo6FhK3+=9sA z+u&+a$kPCmpz4<9nja0AESeGuuTdv#rIZ2*9BNET;7BoKNa;{`5{mGJu|4L{X1Edx zx;Z-k2ChTBS*@N}yE(J5c6uFmI-}#03YW&&kJxXg<)!Rb1})&!!ot-gxKLtK(k1>faxf@^@bS zgqM?MfM4&hfwT;Jn2@9LZj0^SL@?vLg08{&;vCx+Sf0d zjPwo;=TCT#^=I@8-=k9b`Iyp0CB{^BY-8oESj;D8j+`J0q^g8itXs3*(DdlQrxWOi zWANUgbAK02<_PA&7KpCOM_Cn*xw;7;>)05@2Oc1ph@e=EqR?_DN*D&7xDr~Z(z&64O~D0DD{e;Cd? z%kU2iB0n-0((T6CUSW!R)nwSua1fdRoId-}m#y6NJ6FFe?L4mkDf$0W{xeJ$UNPe} z4n8xNGLw)Dz!}&#EWp-oQc?gRC|5fR=pIEgm4~W@MIxjxxw18r%NAQIYA4oCtmxR1 z-OhEy{4#8_acGD27SL0RB#%PU^X^^*P9pNEK!K*lG!)<@P;vv6Y?4-J=FQcb)>PHl ziyMHH;1(&sNj9#aDGwOj`M%HEt3XT2fsa5buns^Ge2fEc7d0U~&28&j$X0|fgv#Y; zacb?)POBM5(19Z#<~;!|i6+ixchnQ~GqRyO*cdMHxs{vtbZ4)fr_Tj@jxv-2HsPOs zik_C7e0_*;ssb8~CHvNOKA|E%27%O6Hh9p;(L{e@petbo5w8oj>Av>@-ZUb#CzKm1FAFv z|HV8^L*+6yZ4+iG#&X!I0!wwNeB-#QFPu8nd|)1i*uB~EV9}z;rI+S>`|aDkzUon! zZ%TIS`9VTs)MvRx5x|(R5i7k^mF3vSaPwG`K5OXA$%DoG5Z30J zIgq?O+9W$M8naLvyfnVGz*0u|2n$7gL~_>$ygg|nU!aWTu)S*Y3PL9jBDsdhlxMv3 z!|3J|U3(+f4}lVS^B@Td0S27#PyEjaJ&}#*TcJKxNw7;>JD+0%&Y(c##4i2(7kM9D zuE$}PFP{(Wcxf{OR((>DsMHE;p%NMRQZv1LO}|dM3D@Ci%u6QxF9+GjgtT!Z5{Q*| zsONlG&|Fm(*jjR_B=;zuE|ulT8j)j*6&PtLQ7C(im%Tkx@=y8qzRGRQJQA)J@;9}1 zzNV!8t*H?RLK;ugbS>S(K+yNb^6($h;0@>7h5zW<>(~8R<@hv-pjt3Sf_a6A)|fv= zH=Gc#3{%--Xbunlzw&#zB4WGyt2y zM%&WOV1i(~An(q zp&KgQJm+Dby*Nb%-QWP8lr{m-cG(zR&v9?U`Qqe});`TfI@FcfUS2v*zvLsD1Q!?A zbh8>5gy)d=hn*AM+rgj_=ch=#?o5iyxqrF?@^{c+|4w)VUkLP(RK)eIh~wgTh;{9O zjhIrvGLR#(_q}SO%T)wUdlh5E0YAn7n0>3&#kx&zyjafwI+lVsN$!DOKuo510?$_>{$B<^` zT7|FO3-;1i+usKHs^SZs=K@_7L!1*@wx7p#^6X`*gv&0dX&GBlxG8m7;E`NY=VUSP zo`?5R;8~!Pfz<;Fs}K3O(j62*f25`l)j3W|oGq*(B>nQ}Eat%}!W}dBb?txsp>V$A za5XW4BuC^o3NXyp{~uYQTOXc#_1w8RiM#s_zB5T>ovdqZb4&w`p$)}Pu%{7PAx#qe zgR-BZ5m1P7(5B})Sy6f6nO~ep(n0y{kCL{oiyFo#Cnb70(w4HjYgZ1tHMQ6 za*-Tu&I>mIyDt(*bp+!3*x#4P!*JKs!}1Dl3s6|XDl}LQGwO3TtF7d^(~v=YftOI< z?2nMjgKSCD_IwpxZI%jw&(qCxi1OJJ&ITa#pjL|&f?ZHeH@$dgdWA7Hrn%*2K_emD z(S8Z7omTMmupBF2ohy4Q7n2mwIqcl7*}i^pqX}SQh<=AYAmO1fEo%{=cm~FEmU^F3 z(BEOLHy41xR5@*0LOQublzxIfVqK}G7h-ZZp~&Y|8%>w$&K`~}>tv<>ID32K&aA8n z9sS9+%G}@Hdh79ToD$(9Dyg}d6>p`8nQNr_Hh}NVl)$Mn%~ETDyIB-97+aLUQ>l)m zMqoTc5Qnd=uDs)cS-b_iL#K>k;6WJ@H0t)znI1FA3Qpxr8g{_Gu&n2Hjqd7N7xb@G zj{1Ooed`astK-_L!H_v5d>k6${hK(;QF&tCi#}$qb927Z_~jShQLcsQ{95;JV6y1) zu%k0`RmNN14UOi&(4i*e3s{&VH@ynKZhh~_&HsG)eJhWU0838082A6M_AYQym0Q?& z(TFn&I)EjJ%7};;j*5an-e9~W2&ko^X^7(`A(_AqUea&^Ml>xX$wcvjg=iu|9WEYB zCLq&1r35JiDUNm#6{SK%aAtqcdiUNl1KK&?_y7HII}Dp)X7Bf1@47teS?i5&KhE7Z ze&{h#dy$=u)H2pdiy7Ajh=87?r}*;fr55%=Lk7=z!BmOHCVm@owADny04Uk zWWHCZe%02iex`>}@JUG@iX%l=Kx$q9ot&N9#X>Qt$^fM zeuZgH@==Gs_1vj-6{{RG!m#bp%uCiE4y>Q~nuatc88Bp=GvJp1L)K<2RK>#1TmmSi zb>Q8Fmns6!Mm+44@IzXMcUtKp^0DQUIXe`IR@AaQ-hvK z$lp0P;7ol?4Pb%{z)Do%56I+A)ZTRu^bJjpt%tsY8qJ#Jl+_k?xu7&nJ#igj2n`^-QbA)CGFGT2m`awZ0=YOzHxHu>?$zS61cy#Q3ZH=)9|k)ep_#1DiSt{mD|dOKj56L=7WBHP*^wQFqE(5khC zgr-v+VJ?E)e*oi&S4^!myac}xVnD`B|GCs{+q+f1AGTfrNdfi? zP8&nv&s%70OL$(=u{GK=@wF<_S1(S>wiu`9hAJ8kj<4Fj?7|tK$lwrS zr#C(kvO5P3_ndqE?Yb!dH)7vsTVgQufnES2K^a7X1)(1k2jzNBTWgrF=~FM;PDnB( z=6T2EnFYOm>DRviy`IlCAaAJu+0_;#TAdNiE6DS2C+wIv>C<87*|3-%M(GImx?>c0X%aR$dq4|ERFam5Oau@T6arB7O zTVE)bBtWCw0ZPS)3PwQe5MHQvekh#r(>FsqVy8^0yr*5 z;vcqHrVwxWt?xBRBBxG}&}Q&p2@9qO?H27cdfgmh6QhGUd(dhDpFoG~_W@nEKE;mT&YlYBUi{Ba0vsOJ=1z? zrM|pJ2;Uh2CL#4H1i4UnOU}{hQ<0$R@=no>6_1E3y=`pF<&L`x5RumuFL`kPS}iuO z?jiS;I44?PC%!>IQsmi&1>4n#Ewg#=Aj38-IRGeh?W#a3vFCKb1^v39!I}GPyBopZ zoueA&In(BOG~Dw{8*=>i(OxDOnn#9VFF<1`hURmfobuP;k+9hTWfB?Ei|91UdLn7j z`|e)B`c(s&8*OPe;IWdjCdha_jdCVDAykZ^=A~TfRjH`!dGtu2ol6tTKJfT4vJWgv zzwq_yt?OkHyD5O7Xv+*WQjZjVpPu(gVhnkljPQkTdUz*j4mVWm!rX~UndEs71Uf+_ z8{_(3*;9{b9THB20LyeEb6GNEulcP5+xGdz!NIwU!)kKlWNYAizKnxhP&|BCp>TT5 zZ#{8v?Xi6fdElW(>IWAb`?IQ!v>9j*jQ_BZl<0+6P>1J(xL+K;_L@}QG|$;Wvq4@> zzG!F7c4`^w2kg&iN=iyvUG3t|E)d}5ezgn<^*%8K0=QaL+*{VI+qvqRb1p+B`!j5d z;y_RpX3t7h55;D{{m*+q;J$Z6)#K3RDI;?39D#g!@~#M?9Y@BAV2}pIY@4K-TW)(e z<8W^sBKp>eH=|AH2UN1jw-fB0Kkqbb97^2kKz9a2+>*8Un&46ObONhA{*48pWX8$zN77 zbr<mxYn%o3E?4J$LzT8cAe8iEz#^(H*YgE*ft5dF~(YA{3U{z=1|)=H&*F}o?M8O z!7G#Q{IiGM)-%?_Z*@sB&VFfn1{}pUC2j+a1J|zI{Jr{&g;gNa@I&nRZVS;RiC*Jd zGJE!d28}K4W=LT=k+ihGjD5CHUqO}J;K;+{Dn}?t`mm_M4DEvA2BupXp}$rl)2(^i zWBD);HJw4gS4vts;&ZC2+v^2FgUM%rL+7t0sMki35jZwW)?zQ~Cb=+b@APWMulUqh zQ591aqmI{w8R82sb0j8}uE|o@INaWFDxK~X_aLLRvmbQJ{Q5|m{6QSpUD8{#h!c7*c8bFWs0Z?Xm=lE11wHS8 zfdUA$73Ko9NK_nmpxfCq~#85i0Osm`3WQQ@)I z?ANieGhR$y4sE(bUe;;C~w8E$bHA1*IZruD$ zk=+5TH4p-jStwLNK@r-1wOo?o=oVWh>2ZbDO<`dv!Rt?i8vDI&y{(;7CZQvmh!lhu z0V)rfe2W&nkXv{n@bFbhAO=tv+u;(XQinI?_|WEa0v(I3d*ZuLj$>;yWEdiYB{>Xb zfsW{uygU<1G9_tLf_3lwB$Jv%9~a=p%}|z?GR1pTF7!;ZHuE$9!uPI^b|0=i>*E+Q zS4H@eo!<(pZErci7l7>H;Ca~~vV*X}B03&Mww>rV1;0&TS90(<$!xUNTv}%T6;hHa zhp)=rAKyf95MaUA5V^#bMC^b~ku|JLOs*uiGV*KhW&Ot347UEEqk^p43P(tnDz7wc8&)w9VYFNM#EmQH>Z_P>mjq(#MVr~IQmxZxgv0NyA;@|GVt&zKS1In#v^``0lj2dl|qn9D3VGXbB}_2|dM zDv>*RXr~eSoR>ji5yQD706dHQq4hkAd!9<&J_DP#qXbm48Ex50%4D$+CQ&9IlNoz2CEjYYr}MEvH2S1K-C9-Ba8h)7qu^V5`S zDf~!2m=Cwt3WrY85Oo(&er zp-M#BWMZr}cvSHz$!wUIB>(LCK)jcmqbDjFdvfz5>dr1?#56|lf}2xR^nz1iRv$N+ zb-8j%gyHIApEPAbfdiv8ZwRf<`dLAynWhT93EoOcQJ1JH5r}m}4yAaVfJJ6#Sme&@ zlG?!YDKc_Or+=lgQc7f-J05VFZ+?!R+le>%tb|Fl%@lk@P~jazp*jYrF?r@ZZBp5n zABX)kh_K+rB=x=sxq*B=$!8YM(Jy4pWfJ9rBu}mioy0}-0Q<5ab zDbqXlJ4cVj!C~YJ=0S<>k7a=z!Oiee_z16Z-S>`AF3_SjbMT!sX#VA6wP0ZcZEbOg z8Y9Qw3T{+q!do)bC`3e7u9VEl2s#z|Y3X62yWLR%*2`UtBs#bRgd)Kh9?ndpxyRL0 z&zfONQDv|+(Rz6vQ>OBz1oEii(-Z#BlLkQ!pF;Oahr_$&_)Bc6YYjS0qJiig_Nu?W zn9--6ihNX1r~;l%m7}QAU)EdDO zmUspkFtTP0<6o#!N1val2t-`&hVGortYc5W#aKET&`JjVVf5X8T#t1e37;SoF*acv zC2=S(*zc8MH&tS%{K!+;$Mb8~q{TD)g}gIPm3!pkS4sAh^WiFd=akFC*F9s1@hZ3S1{N zfpD)fkVuv`Y>djDfv^?qITjL>OWnwC#C!IV2l;bo3>!Y0FDeQ++{MW8+E-w>E6`jB z3XSI1%~2V@wgcC}LsE5!gP7mQyQs{%5neLygITdmCh5}>AY$ESoqN3IoZ$}h`#%7` z9R%$wfTs!$6TTi#!--%4SEjTcqyg+02LP^8O`$J&R)~HT*eFPjkOG5_g^{ZC?#r#; z{Bc>BJe0`pZz7=u+gPXkNN>(p)ba1hLLg-~8@KB42lF4#sK0S~*%{s9dV>zVJ1`o! zD|%PgpBrh|WY??@;!W7^ z=^i8w+|CD80QX4wLFs|G!XtfM0Y8**Eu;@u?7}StdaQib+j!6Tv0%z7loF`l%~2N(DY^(a>6T5 zTh`okPne9GGfmv|Q>!0u%6X%qY$Tk53KIY|UrQ3e4$@;F^h0ZBU9|H_dq=(nIs@@S z)!@6x8Q=Ol9O@1P&B`=1=)<@v>sDLrYC{{#TP$|A1=oaUz^gp&EnNCxg(v<)izjvS zYx2m!MmbeF60X7H!myd2e%Iiq)AGz9}#wN;F~oSl@ue3(U7N~!n&rQ&Bh^{dx(^&Pz-Gr zRt^hB%^w}YlNb6X#?}jQ?k{Gt5C2SqzsDa72ZlpY0i>4{x{Bqo3wlxx0Ay6B`T-24 zBKU-&yLCBM|L_ddr{jO(42s{d<%rd|rF`iulG_`TqTL7LrtDjOy8&(FZMJt6l@r2p-gIdQ90Mx7ny?~j)MFk9K!G&r# zPxzK!D%==J2ef0Qs(KUjdDer6nP5BFK{v%Hara~nwvd0n;dDbUENyJT2y#zSkM&sV10%Kjom-tKB{WjqM%7Y zCK<{G(IPDuoMr2Ue~_G`_chOkJfb%x&KrH;B_UjxSFJ8$&j`O^qWqZ_-Bt5LrZA~z zI#(hevB&m9Qp^&!Ja6pLSK5 zV1@jx<)(KGbn9#5!ZjE1rIii>fKFvQLssi~gFtIqX{GEI=~)+bl@l1Mmu!Gg#!+$x zWjm8L(6q71U{hgt#ku|XAAHGez1e?Bxc;ryB#LBfhTQe zm^)g{^Z20OU-8}<^6js*SgHeo98hImt@R796Kyua^`q1U;!Dqc&54k>QQgyNog@xX z;mBlrx0VmFQB2cx%4BqOuKr>C0L-nFwf>fYhomfsG;4C5EfJ9zMptac=+=3JIH?k6 z>}`E9384iM7NNz#L*yGEgeW3~ z6<@=_&ygX;Wj8oz_mv;9dumH#yijA%i0`+aR%c*PB!(*z=NA+t#obxGy6r~#4YH^= z(r<208UB7s_e2is{ZycveNc(bv5;+i&x5Grl=UFOK=mu#wHlJ27vO11nmYW)TKCG|)UL*Ij?|2f@Q4U#v zs6>HKvfH~3+)w%eD!3qH!UMnidc|Q)xl%bPJ6%0r({v=OA**5a#rv0a5ivD7ShcOj zRh5eEE^R8V8MObTNq|UNp-AO?s|2VMmKp+8<>E@NTsow2=_x4c9&G!*W7FasQNG-8 zmmpWFjV1(^D*O<#j?ULX*>$U`LDV`rVs*4Xpa1b&+eP%%uCQf1(vz-YUkr1|)cC-_?>0Pd7;mIr= z4W<0G;+{8P_+$mS9zh@3jGYV*n~(lFRiqhslV>V!o_z8C4H%v?IxTv52AwIb?V@7| ziOUw*w8RD2yJk7b{3Z*MX{fTtZv_iO6b-} zQD|NPs2M>BwDs0@IN)MYfLXOduy)ZMyJ|_T+R_f74(QRLtQ*@GTedUC~3u|~KZ)egiVLzHjI41vepQ7%;k zB(@p{;V-R#eA6~mir0UXd%aP%FEijjKlU}%72LmK&`h`;`M1XMamO|7X+lUFV_ zYvAs~wZj^CuVwFRSSJ~o6&owzkMg$7Y~^f|iBLg2gchrZ+7bB5XEOp7HT*IB7b2c%Wl|;Z^H)c zN5@RQ&~C`@#J+dcGcbTmxp=_0N#kiT~R0zGX z!iZ5{7`3EvA!`2Z&lKdXMKv&|!MIPw;u%y>J*z?kLKbuPqQI3v>TVg!FwKs5*nIdO zZuZDQ{dlz3mwa=FWO-CEQBV6k=eA}b-b1QSPqJPHON~t}ny;eocRj}e!Ly%pyoWuw z3#u9|1qt5Z9l<1#5&DyiP_?Psg@$Pjh`4Zg81H)C7XvoP3@zYXCw#|6e=%DADCxU* zV3I&$5Q4S?Ai~>>>j2`w5K$g}TR>cfL)?Y{7A%aV6g-R**IZ!~#6)CCcE;SUYaotp zxDu%L)IgY)8nE+iCUhx2$mzo(GhGKQOdQMwMeuMPd&YrX#U&2bZsYS-uRqcyk%4WJ_RfSM zvYD%)fDEMx2-Aq?4{TaE@x#_g{yfauPLAxqgnthR3lSf(^bL)?cgs9?_>i`6>6wjV zdAL~r#}#_>E#Q;E3HvB~eCUzYs^km)S;n*`lwbNEX+n7eXDAo$mPS>s^t!V5jts1L z87UCwiP)akrd6oQ)7TbTvwJmX z3DCKrz8Kq0FmeRXkVvwg;oqmeb9MH+t5f{mHxEGq?#z8S?HS4Tjg0=c+8Pc9S;j~- zs(7(GYQb5U$;Kc614iZAU`w!#kFeJss1i=p@+0AIm=Z4y!2BT~nf}NAiTdAr`#2=< z;t4sG;iFkDP+!330xKR<>kqiBP`>?0`>`m1pFvet122GVE@*%N>G-5ZyE&?8vsD{Z z{cLTrAeq60@+hA#XZ)GJUEwdWXQ`;Fp?-Eo-`$xkluofQg>vKDsmldN^AX76Ra|M{ zAqW!;bu~EQoS?BOT4Ze*1cFh2K5HJqeV$2jiECu&-)`($awqI^p^ej`@qU{rC=nu) zYU;QX!JXpcQMPK8Zv1ZUK&O+pCm*{+X+Hc>P=+l0`eS%?hOqF4D)or8Bh5N}9 zs%k0zQ(CO2@nET6>-nr1$$K`NdKdu|(ZJrYu0~FVF)Uv;_ahe$<4x}lvxsH=S?$g3 z$1A|{j+&Fl`VhdygO3BMILd#iYmW=p23*gL`esgv;PgpS_kQ6UD_Jh04j9Jm7U!Vb zEe8*AAgh|zdcx|f4YpZzZ|uQ~c`HKxkSS+2vlfQLN5?f;5$+d=xEV9Zcp0iANoxu8 z6FWs6UA}zb%@n`PRJKkrDE3m<@!WkI?~|8@*S;#mg@{w4-TQKWdJ`N$B?d12tNRWqaX0M! z7!FH@;x*5j%dc=-d7=*=RI_$?zDjT+4%QN!$FgWdN6>KktxG=M@>0>?FgoTAJ;cEw zcOyLm*>(e*FdydPOW$M5p8x0PZl`Uij78|<#TapmKJw?d)gvn6xi@oPS%%MAdpPD+)Q~{e$#+l<&e}KWi5$YHS1#Ol&*~3pzqUmC ze6T&|FtP9Xqi;t~N!(Nu#B&`8+h7JtC|REofmXF7CnSw5sfkwDV22>73CyzUNM6Z8 z*a?=^ggb;38a#`g+@ptih@qxOaUz) z8Egqgvb@J2e)aONw&2^*o~^Wd-ZjTh4=u}KSs)XCgeu%kgog<3uXE{Rup^TjQ!RKq z#rw|EGO``Ej>&dOHiP35*PaXd(yI*`fvi36=#ySZUyaEJiB*(B0*}yCo|+;lQK0TE zSC6`)Ydzt8f{`H9tb^88{E0T5hL!#dt0ag36ZrQOSI7$bKA+`L5r>pEqvyU!84)xZ z=Zto1@X|p368pGipey}B82=Y)KJqH!!DBqKnrtaG2!W9?&iCT<-BebD?%{(lrdB;e zFJHcl3{VYMn-^2n%EjP~|8(}*_IgemXc2TRkPn$+7pedmNVA-?CHfs@p(B6CJIc%C zA?w?e;G*!iOcNVKTs+XF_Eb?NCEA9RM{U8|{_usJ<_!efnc{1KwC=u>hZ>CE-fdu$ z!Mk4;URY23S>`Q8?ar?i`|tsQ%tChK&iMD&44kTP#%~R4jq+&}HSh;sbaZ)&2Y$gB ziqanQn-vL{rqH$L{rT1VOTV#M`i(zcpwmk#m68PfC0P$pNybTNJ0DK9ecH5*22j3; zl1s+b9(&i#kKaeXdmOKyat>L2row4?BTdQ0f9Z=~ad#*BAy{}1odwxYFaN@8uPu0Q z&MQ=BOpqMl?-91s{_?}Rj{EghTx*pre*Lh)D3hEpISa1(yzot{S8KvY|51=Zzouw} zTJf`6rNM`0^vQ+KlGP9s%tgC3U?i`;YD;+A9Met1Z@vx2dyOt8E33CvK@aTJVSs8u zOg9hJ6($-ScyM7z{{@Xu^~SqYfP-s)8W`lTmEXyyTa(4X5e;C%!}isjd}=GyyGZ)V zoT=PHu6f#;sq#b{1+aoNEd(M_iqUcX0RC_t+t4%P-nhxxR(^J0r7Y%da%eORXwQ9+ zuXlU`=5Dn3+{1w%<9*Ve5`L%hI!lX}JCCIj~@)3f!0y2R?2dxM$~F zQYZHD3-#Q`J=U;!l^muEk-C8ldwIdf`?dYQv7I+<2KHLvAmPdvCWwxp?zFD1MaQM% zuWsS~9iT+I^t+(gf@XqM&-096^5_w3bJJp+~w!PAC{E3|h z`r?n_SmDny@=br;e%vtXvUguG2X#ovW@kNchKts~5gMe=s0|RP15t~@Cn3DvoFr3Jt7@mx6%pd@iTyi~ zhQ`70Ob;86@tej)A#L=?x^mc#g+QrgYoeS30H z6jQ zX8Z#xq;k(PEB;pU(ONp7L=oKki_C(M^ZR}%8nNiNtnYu@wK!(x7sV6eb|EkL)9#?g zA?4~TjYD$liluI+*R?i|syT4nTJAde_sGT}2kZj3EVhoZ-PAK^q(?*V#j2}%+@=+(0w9h&l>&AXD~kA!kTqgOPkOY;np zJt=$QBU*M{F+7NAKT`F4(QaRZTWMTJ6{oc~Y_^a2b+v!v5M!M-!(-5k>07^(AJqPEB#psJts?SLJm$4{RE{p)TI-%XJNB<}MpA8{Nt^^x1P@in_Qy_|09--^Z-u z3}M$AV(K4wz4V5Cd+2>l@TbYLst7}IedF5lh_E!Z!9$Xi^nl|^2W|ei?n-_9qcP=% z(GS)ccl)+S1cx=m6mh{Zx!jS4#*N3r8kW~{^|ue`78^glD*3qnenX@Bn9}Xx?F_@n zuU{#?ufB6++i6W`L3LGq%=YN1vxAG;wmm4F8BtS&#xkY$S4%WU>NPDze`YQ>7Do?W z9Q>dj;b+IZn}KL`1<=boFQ|EA#h8`nuzO}hqyzR>atFsNFOYp;U7Go`*B!AWzM7@k0_RI zGi+QKt1<5PUwA5X(9S<19>2YYJ8~iU89bIWz}y9m zIozYBf$PxJ29BBWQM`_8gFiRHN%QU3 zlgIka)@v~a7^ZApF|16Z<~~;vf$`$hqhU>;3?Jq_);#2D3|z}0gZ~W&a*+&qQ#xKN zz^>2SX5YNU9CzZ|0Q-d5e!uj8tJjO&`zNI+&na%Et~vjDFX4&hZw95CU-GT(n)Bm& z1-|9R|PxY;?@w->ptY zKfc|ANT%D`qq6a$Jwaz+z!^QE7HI6@3M3LJnI~|pfZ!u1 zJt}p273jZczlEp=r-TP0VBt?(w@%!pF-|^M`Z0V`O^9)?0gcl?<8NG28+54JKby|Z z6~-zvL*~`Ks>L^|@pxf>4K)01Vt!$ZI*gVuM1>kI;$Ag(B+F@`eC1NK;I$5uIE9G= zc(BrRZlQxPC_ZV(RMU$?GpD1M9z8%LaA&&~$@a%x9KULSSIXXV%8we^93VZ&p9r~` zd4aDPMk*^m&98BP9P!sfyoWOe%m!|zAH0iWY&2`}>;@am^qVPO`cx+Yb0^$=*Usid zme|LDiwB5T>7D^)&q=94))wQSDHtu0t_E5mNeR40_wiNdnD41`tVJM+j+SVU-M5F)I2CkM1c*YmZ*IMb`cm&kOyOK z3nxn0ORio$o~uE@7>zui^rztksL|;RYp;#-p;m)0?2Gi!qS;hU>lONP-qknW&C1{^Pn@G^Vv*Tx_Wg+WX zN!xF%82fByEcKDf+_9a?K8x~L@xUl;Eg-B+WQSy;NsXZ{(oyXgZ*4#Hb%# zw~viI`<98_^k!9ut`AGoTo?5QNd!w}@SF<9udq-mATq-@*He!zs)mBH>Hp7f2XmL* zFPFCKO~b;kVrt^S4-}P`FcAbS1WhnLs_`UtjZnE8XvgQ(Xo*0{ex&i)l;s|YBHAkk zjb=>O5$axr(ov3OooR|N6xbR5DjH`BbH+|!bl9At{ithmz>eC09c5OdCDMOezac3@ z2j4ry{Yay&0tQ&~Buce}%7p2p^_t3+w6J=V#lbUbgD~!#lC%W`wj;X(ErPI6mzRzl3v#y(^ zYrTcWdGt>P=#aK>1M`^vLC~wKtI>6wewwQ2*PUJiSx*}BQrZZIsQ99NNEOlUg>%)= z-|T5)2>T zr}*M?vxuM1(9Qd_aeEsZ1R4kbY?5q@gG{hOvC58#ivm!WT|Njh~IL&}v>+skEz9PG8$?z{I1ZtXWuHHYVkqDJmxF zkb9K3BW&W*vu*67l4N5R8ZCtvdioPm)XSHrc$K9(C1@SDV6Z)Pm7;3iXL?eWXx)>x zr)g%a2|*VJ5=p>PMw!VYVcrMI3j#ML-XAoL_~n~J^>nM~kjDg8YWMcyFkXlSfyGkw zAfY*WG%Bz47C#mWq{Sc#Xjai_a4k;fH_Sz{7ZNa`&Mxjkss(O=sE z0o|C@^$~Zrx|DW#nAD}29MpVQWY8MT5X#MUrP%aZg!t1`&lA}jS8mnTM z%0M#AG!C?A0i=s33SnE{Y%Ksls5SAPMCy^D9hSvJ9!zrzmW}vJkjadbnK#l ze_E&I+ei-&G|O&O9WTa^VcAE1a5B=+W%xP{l|u^aA}2T!|5wh&hTADq1KzWj1pdI) zlL%Lt)v(kqzO#^Ho&HMVHLqV(mPr*0OBrmTN%#_MmXxY;>FX*J{q+$=ptw3KK^0@# z_X)?tQZe(dA@UA6NkNV1jM>D`onTZ21xz*MWMg4k$I(^s-Zf44;ssn&HK|y6QXk=} zn4hr>PDmrZO33Lj{d0&Kd)Q|W}kE)8{sD%a8;?)*YY5{h%<*Y zT&EZX^-%vy3-fzkK|80s_)F-u9G8#<<-BSOp)%F3T9_X&=w*m|V8pD}PqA}&CqYgY zeijFVtQFMs!O!xHXk$)Vm{+=@)&(<}9|fj&LOf{)r!Ps3MXcM`_JjjL7J)4^>O97t z3BF-^Hfypw=O#9Ay79>;Oz|#DXU}{feytRCG6Tb)VBFPddGajPXfaWVEjm!&cSe1J2tOrJjA;wXV z(Mk9L6cBVYAc-ZB%?LXEU}73anLbjkY}+tWz@k3xdPWi<`0fv2Zpr0Au`YQJRj599 zCnc;x$r{>NBkSxz@+mrlcz3~6%0qk`xTbQ_soMoDJcy)kz)<)zN3->KE>EZa;+YkN zg&Q?R5H{umZ&yPGP5uIU>3b$gMxqf+af@9X#z zuWzA!z5J$*v$FX~G!IoP{ZJ=qJy+{AOTN;NpUluK@*VgH8*w!c0|a1unnbD7R_Pe@ zF(mlbD?su3X66nLheKu&dRRNaH=BX_|7S^B6-zNRgu8H>!uh9|694`f=&gNWu}tA{ zIiB(HGzHMqGQ~316XWS{iRtVgr{`0@!P_V#xYe!s!aiZZ2&&*?=%f)*Z0#w1>{qq0 zvzh#>!t{_Q^wiSvcIJ&b%%kuW01yfD)jDZP8u=Hy8w*N>34?=iU2*AI>kU$`uR;Yo znh|u+%BESq>fNM?5~u5I$fJ3GJmlxq)zuyjQSXdB(8Vj+ABV=7OgT94ABw<(EZ)*I z8+%nEn!v-Hs7I4)i!nUcA6ui-({Jz$j8lHQ?kUUYPvai6l2Yh=ui65KRKBNJw|$^R_~Halr_q2X2`(VjucGn9oj9FtBalFzds z%o)PjpX61ZM1fkea@s@W;p;k!W;zBG5T@)GuK{>J-=|_aWXhz(=@Z2kaRfr(>F4+5 zeik;eh69d6aSt=RLhSH20kC^@=)AEGTd zE2dgIdL@5*j`@HBs007%0E`)A*8&4N`l$&&o3z9sR($_V zSwYVUcCl>RC|cD|anG36LrDk=l66h)m;ZGg8z-!9(f;#tzZ;tw!9my; z={lLs;lJ-L3irKAM&GPzWR^jP;J(cQ41!I@7Gt4h&FWbbQz5{@iDvigmY|;_MQ{Vn zD@i+#N^p1du(5aP_;k*g1GSCskZ^|}d*6S}%S*D5jJ2Se zRe*({k(1YagUwjPxY%s?#4}=~%p5wX>d1dP%s=Py*H7K567$b^m|eCALGHW6%m7*# z=u>8;_J(>JYHc6w+&Q>F=d~^;$cNH#FwT+uk@^$zg-L}&~J^YoqEL8 z^fZV7H7<2&NshM2p>r4wzYqF)%P(Jz4m-Ql6j?CUEaE%ua5e;dM?f;gm^$8S6t(n1 zNYX}Y<>0i0&0CXA(Xu_$-c`JchFl>?<)s?PJ$~F=9kJ`(awAL^@6+beI9SBb$qd>Q z6ooAyD!T!1kCfiwWm!a@859OpZVCU8Ch(0*=xvUG_ z6OblPUy4gHj$guCz7GiXVbKR*A07bOrgcY-0pQLfYun0Ji7$TdYA%}Gss3TFn z#UTq=*wx6ZZ!s9@6fi%?Ekf}u4f&@2qhP4$5U>M0r-oR}gELvP0tOTb?dMO)3gB(!YZpO$Q9xeOeUeLVqn5{0~lm;AbV!@5S8aD+q7+7DLE{3zv>GN za*EAdVWqJj=tl(g?~Hv8bWwOH)MA0Q=NqG5!!l19Y6Q{NEd0xW_FzvvmnLX;h#LXu zwV~~I-34u8)-Q$gx2baAo(R`jI+xc;9-1{^z?uPUXQa*3`KoS zFlMwH@Bd!9)zxz$W<0Dsjc#pF{>L@>W+jf%!{C{txG*%JqcD>#3v2=b^oUv`{bLg$ zdw}+2u*xFP*Xc(D*>cwhn8xwpPxGYtOG7eBL`blEx!V0dnaVM;LQPI~)nlf%=Q=z0 zpEpl@Dn5s+GCmAZf9MhBMjv0#MwSKKa#c7KHYaN4F1k9(Ld>bJMfSc?)3|dkXW}iC zG|+fHkTvUVMBVX=5m}p~ZHIN=Jb2!PDa4Ix3EhjbKt$5m59A8uuGO`7mf*jaX`jTw zE!DFPW})p@#IFaFD`F$eChl5{xgBiYS=3JW@@yGHE4TMbW0S&^Eg1|Kn|Cijrqd5S zo3ko|MU7G>WpX(si=^ zV7=?)Nyxr)_tm^h0ko9V}aa7VzUgzhZz~#Y@mZp><46NoA$!d$3vg!^gZX-Aonwbq1X~9D5N6Zh&7If3WU)l-~DT_07 z3O+1i5oXtXQ5D9A(auaHuvbfmx)X^)^w`S#Ms%R<7#S{X0?zDL9evvk{lc}G{VnW| z$M<)BB6tRUn6L#4?~KHJ${z(kYJk#{MHiq(KHnoc ztbA^AV-#l!m7j>6*$ETYf#x&WPl0^_*EulBw@fe76@+{cyz{#cXCO+ph?jYb6ust~ z4P&44^na|__Q0Br5fedV6i&DXFfCW{Gz%#-Jf$dExkrT zfk~a3lWq1)abJ*T=&c5q)RQ~gB_|wV%yn;UE&^aH$=nXi52k#x)I2x=1}f=cEgQI84a)|jwbq~b`0dfjtI3lruy`J~0i+@|yz93_T@V_f?2 ziDQ$grXj1jTbdS!oM@z?VdiJA4G|MbnPQfPK1Otk>FTeKJ?vkLBsM1w-4GEngAYArpK`-cs*awN#Vt#9>33h(Pl6d zYowiPz2)ts^duTze$XfugiKqoY_ne9^x`aw3jay)ogybt#zA;^)TyX>YD9qIb{4YciYIf z@QUMT;VW&v1Ky1NInK&XyfY|d<_1ZV* zxRS~}BMsR0$GaDk`n%D{fELIH1?c%T!!jhMUrsH)^7f){s$VwDnVtWDNi|yhlc=BT zh(Ch9R*W*nhgEmibTfE!jmsKB1v(Z>gK}3oCz5O5c!BOMZ{CTCrsNur-uO4}?GQk8 zXkS6~s4F)O+4hd+v;GymkQ(03L{|6d79LGMJLdCqPS@*I_g%O@V-rfSIVZ$4Z{{3> zAhH!2?yqtCf6C3*ThehpWX}G%#3_K!#UNNz!-E#a{Qi%XL&0%~9=Rdfv-L9EBt$?= zIDfs-7k4Z$kr2=PSp<=|A3v$xST5U`Ur}$FH{TpSj+am&@#tG*IJr+#Aus&dw{xN` z5)G#I^oI4Ps(dVZ*m`FF{^B|!S)VT=v?%S2<2rgXV`t(va538pOmQtsdWLUmh^WzV zCG%}2iAi3HJn}jkc_e~o4`;cPH`qf&arMdeSc{y9kZLtKaCTLELz5PQ_C-tHw}@7QtrvjXClAYo8nG z+Ak9Kh3!Trv*AeQHNgQ8%)PI%0rMjG0`PuF6At=mj$9=ffRAN4Z+z^cpso1pI@Hqg zhG_ZxrcI`?fl%U?MW?o<@NO33)V4-z7b?dHNOsB@a9 zI$XjyW|p*^)RSum%gd>x^!TuaT*;wD4!biCgIH)?eu5_7qwjjuJ`t3 zdu`s0jJrTrc0qe#OYJ5o&rk|q?S2?w*L%<}6So!!GzE2bdJAGM^@bQE9U-Q6E;763 z55bbWhRjUwhU=?9leG>8Ks7r^1J?eoq=md5dTmS{Oy+Jimn;m z2&rqE5-qq(<Fg|Gnb<)&DtO0Bo6iYgzRm;4YLaJwTrDSEoZvSTMi^~-Zg z>q6_Ar~hcTwobaUb)cB371Neo8FiQ(p5gJuot&n%T(S#g3Fh{pT&;zp59DdA(=(M1 z)^=n!mO2Y2hWCxwW5&woLNcRB5Dw)(H7mxr&rk3|r=OQyu8tai=N-=$kUm*f4DqJm zRSV=4G5R!xpK+8?!NRQQjW`q8LJ@O@pGY2LiN*Mk7n#*El9I3p68nWrb{1nz5pH`j zH6~I+*@jqXS4-N>-nMlh4?rPpE?gc6(ButJ)QK+^ga(e?kTmqYT?J+PeQfk!tVtfo z{3{+$HDRiv=MQpz7VIRSD-a=7<#YXg`|zY^C`A*d5^7CP_YHmale^Tb_CWr7U#T48 zw_@m-?lgs_Y6$MsYf{;CBPi1 zZ=Nh_D+C7S6EtpcF0f9r9#p7I9Dk9;V?j?a#|WfK_5_XR;O@T3^g$>3Gtcx-J#U>* zErbtyY<$QpSsV_b-sj?4TJ9KIko#o9O~6GUd&u)e1*Y>(6#Q^El9;+s7YGbyGnsj`vBErd zLjTA&1NNl#Y@QY``0LmQ%YuFY3J^$DA~Aunli<1oST!Lldu8;F=sARmj{-&Z=}b`k zN}wMglhrXpaMJsc!-{-N*U@viR$!MbIGgq=Eaa87xli18y z|Iw{6Bveo3DvRm`TeV>Z{&O-{t=2rAvyM@e`QS5qxEO|JgB(5}hpUeAZA~W&-|482 z8k@jOX$(jN{r)E#hNs}~NPXdCM$l!hap6m`SbmWp=ZCo~KqLD__#&ff>L|Aygw z*2?;yiF8o1E8)4wzT_lCPq4Kh()edSsb9%^lKBu^jfCuI!dh&1$UG?vE9#?OvmJo|~>7!Dgr7hcL)J*KhWk1P}>5G_+{^E`c^%U9zxd7o^^*q+9_T2zvx|p zK<}D;Zg>RbnTanRnabR4L8YPE5q>}fd9Mo5oE;Mp)Y$lY|M3FTp7!q*kP~+ki{_Sw zYiDxmY(kqw4*-MEg)URFx}jYFyR3&7Qc#K>cmn#zsGsHp>+aq+YA7$ZPGB92;MOt+ z6FnJOssC_)5EsL`Uj1YORr6?g6M@p5ZIG`b_l|mtLHNqyQ4WA{CkJ8^u>_URIa&jc6_Y_S++2e|>&Xa9h9l z#RSwch9NZn6Ev5SLS2o~?(hf81HNPl($6cFFGt5PkyP*FGn_#uB$PAW;0)M*0lm#$ zISE0mR3CrHj8qQApapvasx??IUyaJ@BYI%8{#O?fuhxX@mD5(9_m){GMs+@-Rl)n#l-;SAvCN& zSVKemjPJ{^*-MUeg**hG6`}_5qoo=DqZeOl*$*_8WFbN?>mWX9Rtq1v=bWpJ?V?$@{ zf<~=FiGyus>F!M`_f0GbTW52Ew)&vgn#+cjyWgYW2!{hEBjnEocplse-MDDiLmkIO zF;61P%;Jq2&%q(s%ozshR$8){)e8P9QpFgT!rk%0jJc!wj}Lu!yS8Km-DyQ$>!DJo zqM=TY#@b**&2kLGJoiPx+nt=2d-4!S+y8VL;8xLs(Y)fqm;~6rKD67z*^4%DP408E zFWwz$!U%v5*tyK;?`@{ZSk$6rna`SY3vXpb%s#iXx@OrY8O{8#AUkRzBME0L3?B*K zfaR-i?kq}M&iiapUcH8s4P-x2O(kB!@?CGNaP&XQRmfA+En@Cb0>pJ)Ju5l2sJ4ou z%`^dkLF?OBhi(deYi+1rA}+L#8jGBtqE|3Od^YYijZ0lIu|wz09a#Z6XMqEQYO?)q zqHfaOPs1G!#o*znXOHZ;^}aWBH#?B}LLOTP6j))7YDWmakEVIBx)uVrzOwN^T!-=u z0N6q(Qy4w%43ufW#IX}Xq)cb7U^9V&Z+&zx3>5E{g}hB4wjph{Y95sOSv&4W)6`Tz0!kywxELVDA&e-f?ubHjKKp3}zyZw*1~)SF zAx2FbDKL=DnLXvIWftt0{0gnDz>n3pLa3oKH~3bio!=BR^@D37#E9=YzO$nc~R zUyJzp(zE)b!zSvvjyPeUlx6|W?X*@sOScK*N@L z*Zdbp9~OUxSF6y!Ea%tqb8|o33<*4+_ZKi6&XBFkZ#BmgyaGl?$v$Lk?#ch}tw=Z_v9Z?+3^<;Tw#e=0zK6rFVM8^_o39E=OUgK-d2U!mnn93~OLai8R zk?<8J9I0NexCrCMtbC}gL;R`ET^C6985((a5u-Fy z1&W1_@mB%dT?Lx00bvzj;qWtjuv|$D8W9j`FUn2sTn5aF+tL0_*nqME-OgyAv+y%K zwM$4R5}c5M_wFR_H5?2jY$g&J;b%nmf|Z<**wFeXAKOV#%ZOYUV{%Oo zjbKsq3pUGrZq6IdT_Wx)SN@a7)n`|!hX$X#c9qq$qjZWWs7U#ak@0m@Cb3VQ7_z4u z2YCarwv*eD*<_OaF)r;PM|oB)qubDIcvq{~DzNpgp4Pj+hKL9eP0jzEh+jbJ*bHit z^C9Zte?~m`0CBSdg zDJ_!WM7YV#iSoR;^9l!Hcdrc15-13Sf%sr&Tc!k#W}`u6MqtyU=bYN3jCpvgW$v@(I?+8CtTMK86=m_{mv9?f95)zFdGyv7zU1`I`U%7GV{w*QP9iAiMd>EElNeVp_{| zOv!Ax6PdQ0egi_%8 z5LTdW;||B6d4*k54iEx&>Cs`!vi=uCSP>}jmo38P-rNs1;{{1-Z4q3sClkV-o>sEX zTT~p(CyABa`>#3gsilwQ6*xajZ(w|cDRqv(&ZW>N3f;H*-U-%kS=sy|aXOE*oz&Cp z+NYy+5DwuAvdWT)1g`R73()nmSuefiWv89f>)W~&P0-!LLelO|rzEIl!0ZDtBG~xl z=F9O9PbMk8VlfTvG&x~?JE`fTn{!D=9Lm>mWe(+zWUIWlLFVm(9rI8e8|B{ z9in%PM*r4T`4zSjbiqb%TSw(Os>k$xGMXMhUS1Z3H>){gqRnIFZ_q-BAp3sNh%B>- zyh}_7gp-to&KCVUieJ#0mJ9mz)$S#fmfM5<9r4$|kj&_vxiJyH()fzul{Fl9Ez%Kb zV{Z7*485}`P|Lq5q~*T9L>TQ_8y{+%vnhHf(q!rTyTA zzAaslJC>YtP>Cf!td=-3-=E{+=2;Is#C;wqlx22JK=VZp6*N93yg7n1Om?!8qJsm{ ztCWf~wRYh%&gkic?W~0KCHWe?PZnSM{9pR+pX_Y+yRi*71A!LD1}=oz^{W>mM#d@` z^ejfe;1w|2n7WKFJmG1+6m@zt*coQLyV)7+Yup!kt7kzCC904Yw=5-w-&bODYQ;av z6(mRS)9bhNzYl)V>HK#y`oG`Zg@q#);y%16sSlsh8`5z2)T z4^#KZv-j^yS0xU<&r-}!<~>*z89i``6%BZrnMAS7STf@r+I?p|x}KETIB;k0WQ{EZ z=IObRDmBS;5)Tq_oUwYY=i2s|0zUV_Cr>-o6|=%DdsOOZpeA-byL0x{f!)J?0QmNOwiCbOTv;wMk%?-SWdNz*q+0)ruH`CiyIgslY*tB}6 zcs`sFnEpa^V{U1bC|&ZZ)A@^}+QA!kb6g7Crc6t)%B-G^S#?hhv))Ww>(sKXbyz#J6^G(dv8 zySoMpuKUg=dCxg@{_m^5>Q>!5>|)QJ>F$~7>0Z6$S!?~#U;JaFQ2=_@8bBcCwF9#Q zoK_*}IanI5&#TX5Fqy~CR)~Mmvp-DzA6*q9ICMA&p!0xOX_qNS3H`Z?vhiQ>=Kj9? z|MVMprf_h;JoyCF0yP6sJq(5oFWwK?-aPX=;2=o<3f#rgEkOb<^}KwgD`(1){^Xpv z|JMxpvm*x-xKnHgsJv;K5Dow|viU#e2T%}@h0y<6ZHSzISYZGu7J#b*sY8CVqk+JB zC;4Zj(cii8Z(PP790p1uFcCqILPWl-+BirVaQ=lC=Ph9J`K&$tmze)2z>y{CoP%%} z2sEpEqP1WxL`4PqpWqjN`JKO758_S`2p|w~lS*g3K$^5rOq>7J3SN!`+zNQ$wF7Gi zD|nsxT{(hAVzB$*ycL<9FIf=%;f=I@iu@03%mg&y6WD#e8K9==Tb1D8kp~S ztIucZpWD(=0D+^D*!~Y@>$GQ94ehz`(KDQ*L5Av|s6;FQcwo{Cs6GE%)~ zCZt6_`@aENXZU|&oE^onJ+FMqZh++S2VM3z(9b- zX}L&UKn9yc1-~pXl=zRNUD*DooJ<|?8fEI57Q|I4tN+BH1=7gD0DK_u`InRpNTtu) ztVVrRt83jeoy-POBd2}-gRr1$|8xFNbR{!UGtqrclp}zX`1b6M`R63);NarYO6MYm zO=tyB7lQ-*1~Mgx{g=P{*gqkD_x{!bT^pQ$q^W@9N?7}U;|+}ggX_=dAHPfQzlARz z951^4N=PNHl>pZJ9~D><2-FTPaDDjYy26%&WI|f?IC0|HNc~5CM)`{{0HO~4E2wWO zxW)-!U?b57-7VMsTYl#J(>VadD!o^J^Yh;+3KF}Rt%9kL0)*vf1q9gW{JdrHvSJ(4 zc3Gg^JUU1C(f$cG4Hnxb0m)DFPnlfkA90|^N|f(^-FKgD#~8if@t60<<@Xj)5dhnh z@BTvoGd126i|Yz7@%}9x!x(6So{1ko&J61A#fpCYr;WG+1^ha}pTDN#(LdJ(`L!!f zTy^|05dUTOfns3i)di%#?VSK<2_Tq)Uwjoz2 z6d%>(fvE@_{*`ByjPgt=Y2%c@%3Kn_gV^^~r|^FYtKq+alAv4lq1o$YUd86sUch*) z|9prvYAZmVa`Le*Q|mcm7`XdxHpSo#df@<Q7=53jo&vau^9J zT>+HhUvRJvd7*4k{o`eS;Ow1ZAS%TefcsLyqOuC&wjt<5&axY}W&ZWNjE@lemlpy` zQ#jHfbZ~kYumCQw-hQtH0u94(k`eKs3i*Sc?m)qc&=PZ&Ek;=N7~II@_C=Z?z9>NT zl!FRP^^3*NAV8J*oN=~O_)j1(JbV9pe>$K9pcqhG1>XPMg}2ZXIIlN2yEiiFAH>#E z`{#SELMiZoSX2OR7Dd4n>E@5X4XopLWuR5zNVf*yG?4P7O#q$@7F_r1a)Dz2L%9k9G*m7NdY5uHZGgu#kiJL)7-s%YN&kRS zzg69?e#8+#1H8-;viyN{`vi2HlauY=N|{n_J7=6$1p@7p0`-76tjVYFDTg_EYVb4^`qMKTz1ZKdl35fhFQDxN);fTkD6|*= zS2_Tk4S`ts&-iaEEzGzhgVEw^0k4_CM;*>X9YzQ` zxy|4lP61f>b5;{kAcU|WJl5X~2u~3|EL#9u0KWK9up%M#6Oj29{7%4%`Z*D3K1iGs}cf6SpyiPVasNO;0|+>XNM6GIDY`>ff9gd zTLXMXYB;lQAP_NZkDT97mA}3L^Z;aW0b2RDsdQ`2gDYeoOg%84=@kgXA7}Aqe(1_s zAZyeD+}IP?ahpcwunwJB2u!G6N`o!1xxnxMP6FFAl<@nP;$Wmj;ME~;hJd^O?=k`c z75pb3{1t=f=FsWsQ!z&`v=k# z@M13AGiDd$zj{$hCRg{(w{2#19j4VTtij+41ke1Ffq3@Fy%POxmfWT8b9NPtS-7RX z9;w;GJ`C)#y7q6@|Eg_n0?9VsOW=dM*Y6*rN8f~j{(B0QsjQKTkaVK#^EpKP&{B@g4&57gkk>2OeZ}5%5)-T zZ|7oW=i*Gt#tIx$WmfleFk@CWvH<^c0#1-}fU}~gGOOCV7`d2{vM?){nOYf%+I#4- z0LM95*+{u~*z}mioa`O`eUKeE$gan%YUXV3>SSUDG!8DT$}FnO#Rc9W<>CZ?=?My= znAw@y8(X717XWtn`I#kwI|6^PlCrY?xhF|BVE0c8l5a>^S-^L%$}Gta?EbkqNe*E5 zxn*WaPN3}H0$jlE-vZpEtZZz5s_~Gr|J?)HeDlvPE9slRMS(|p^V|TC!$sN2-bBsJ zMVDDwT#{Mc%)>>GS;E6bN)6l>z&%Q-0XNC={49dN_OFKl-}aw}kvFrm0J6Zava++W z{*y>X(gvt4Zf0U{Y9=V??BZl*WQ&3*9Z{z_n7GJ^`{k>e8qRb@?Mz~}YNv;g>b68; zx_qMN>y1hqubMon=FEC=H`;G}Bh>yGw;y>(;brsaWNj^EkswJwcsr8p=G^}}VV-+1 z=es|!zWVi&!{WSL^Nm#2SLa9rd^*VzTw^;Jns@29)8>+kqc%_Gk_ZKgqg5$dEnaD6 zqy8<8UNJ4=jZwE)h~8CC2VAc$=Hu4AY2>ghitOwULkUGo16h`Ag0CiOMjz8Z=}4ke z)d{K}@>1ZXs?z4y_|LW&W6(5Qik;P4G6hp`9%{Nb+%mp^B;60;E zZ(u5eRB#QhE(eC_i-O&0>v#bT#}%1Tto>weJMHUzv+-tx&l9rqly~3pq5~1QZV#Iy zu$XBpQ>Xowd-Vut1kpP7)-u*2B>eL%vvu1pac40ZSUxKYLR2#O&|A1N*K!<9?5yKT#4Jf}xBxYBh~fXqFqS^@$?C+5?=->{!OLhP>(N6Bmw3$U^9-Vb;7{uB@=z5NqJ;l32MwL!-9l$GnugG)oOhwxquP znle3HR6!1XB9a}V zxCShe8hbxj6W&k0iMm#IQHe813KNmAF1S*HTR0(cJ35TP!QHV-LhZECwfi7#`{QoE z((b@%+m`5x@eo=!bnMVnpAhQ1rLE!-Xf~e^k{psn2O_ru%K{&Jf24b@iy#r1<}^!o z)Hh@9u65!hoYTY7X)73weSm0`*lv`eFxokv=hf_imT*7~{7LTC(0M>u9Sw(!aE#~P z{8-gYmr^k#6lEbtEM=fui4zRThrx``h$Q&su1@kQ2o zIVGZZ66?n4!HONJPPj)N)$aYlPo0w7=gDGUwrrE1MPWQM`_YLZ;U3W=;gHx;20M~2f<30`l*rB0yawJ-XLheI zGQ5`KbSo$A;Z>ru;(ye3(zZ3d*oW0kCjDglBZ=G7(cfLu{@z~Cemv%WJKu_bejzu` zWR)^_-1h4gtUJaoBeP8OKEatF6la7C(`K*03uIHcYv;n2vus%|>r2GW7O&-xc`ODW z753iZI(Fk#B@;4;mL_N8PLr}ktI)&s@E~4ru%r>o^)v-ZT_Ao#0oG79t?5ARD~-z} z%eOD*td?iS8^>IcjyxLLNmYkfkaD7Qy*lPNnLajP=s=Ya5k|PpabQMqU$fu&@m1r| zOgVYN!%)nje72!wlOS+G?+K|`R7`zk5}^w3W`_Qi*Hkt$RwRAgWvW9m7>1pDv14oJ z`_R@G{**m@2RFjkJP;|`CYTaR`P@TUW|Y*%}dvLRTGIZFN$$Wk~E;N zGZmpbl!>^Qe=y)CW8YUNz*3$8VXE^e%6CFuP<{J$0qLTHcH}QwQaT+LW{LJ7+FInq5V~-9n0GetA6MRtEalE z{0)!(*VxbfW%L-5@38~r_)GRbB1eR6>WFpj?k`2oaR^`Tq2Jb%lEQp|Zczlw;q{mUpo?CqDnR3|+ zYt`{O&f*EO<^715Wvm+{9s?q?itQ+sJF*O8E3L#&Jt7Ajd!5a)~kS(G;6H7M~Cg5g-`Br5duZ$%j#Zf}*t^ zBmD+gKego`ggk1BnX`%guX>-{I0}poA4u?h_m@%INF~gMl|1WGVi|G zK`(p43`6m0OaC+>_QTIiz?=2{;2`<(kx{T8tK7$_OhHVN2m4{X7_IA;JH(%2Sf#|* ziS)SNRMCkYt|wrN#)5bhmj{~5QOsYVRzm3$HxN}EWVE)bubxE@ey3ah1N%Cs}?XT zmxV_XxJ4(a3(xHnEYT}o8F|B-MrQ2K(=uJItUcW;mqBX3Dbb6VvMA6HxgDp@54*(1 z&tm1dCKg}o@WtULJjPwoTR6SsDflM!QSW7=&5IRvGD!~T zOJA7G5}Rqbmlf~L_|o9Tj46|)jbT2#$*}~L`b8OVjgb<*6Q$DM6qo<(C3ygevz^Kb2U|kGOWblh;&3Nn^>bHuGfl(1MdW-+)`W(2 zQ=KS{7FzDAn@4ySabQS-r+Uf=?J@f7gPU)krs8+IoT@QdYMIW0+;hZ8Hzzk^vJFM1 zzF)^u>M%xT6|Y>i*W)~)4c=$xzB+KMI!b3(?6I%$$_y#D)tEJE9dUOZCmI=F@m2fL z8#<{M))IvFRI~a;=$LH16NP!Tb65AP(AY0q;dYH1&04G05P7%zBRzdr4RK0^E3%W> zllyI7ZQG#u6R$wg4Y|er#I1&}<7958CU`ishL0f*eo_eD#F5%lQ0f$GbgVwVk(t~U zk}$0{Vn)(lPfeEU`DzCv%cyqs&lrWD6L-s~pSDH2S-)Jx`}G59xgMEUGJ|QpJ@z1v zpeYYkzDym>4_DiXm3b#`sxc2*8F2&>hWfeq$DSSSrA7|IE^j7${Z<*fBWd35R5U8&k z{QMAaTZ^{-ds9%1R3TxOBHZKtci2{E30cwBc`$CN04!YBOJ;6}!1wu5)^QV9i5g-h zGOyZk)d&~XAXH2)5=SB>H1cUg`|q_|ZY)(Obc68IqfH+Cp57&w%)t8||Aec4uy$c_ zXyAn;k4$S!*xWRS@A~&N&qWCb|)GhyVcof1E zU2TB-!m@7CiCoc(-J0?{8Ud^buB?4TZK+MoMJ;{Um^$ryYD_+?f=#{=?#yUM++4a4 z7@VD&W|lHltDZ$hbSmg(y3#fsJ^ZjKvdCVM?^#tyn}qpsN+!cLdN4W((r!k2Yg*Cl z)@(hV)(sB%n@swj-4ax-FC<)lMvI_~Sr+Ruzt`K$WgMk?$lWLjT_0hoiFhDd7fhRL z+(OoGay@vEgs^L(>31{1s7qp1?ICqNeKq&pH}PoYh)WyClORRsz3BTG#;En=7lW!Z z<;J!BM5$ri$K?;3#9jA9cFEU9ux@c?oIMdyq_qvb_b}nFxCB!LrcUx3;x!P7_64;n z&u3a#rsy$Q%bj!u>k}b+B&n1n&IK#bBGiwhjCj~FmZd-#-zdU`%P}xYPWy--jt*6l zlS9!~$c^SX(K0QDS)%Q-XAG0(hkwdcaq=t-Gr_{B+ zr3^8*8d|5?4vjy-QS>R+4H;b@zUfniFEPYUYx$ZowzB)-MYptLn0=m3rE(JSWZWDa zh(+HLxouT(VmyJQcDSuwn1WfUzLtB)%$WMlr0&ItjyLwWIz~;)Lg|8vJePWLM(rok zD^QyB*C(`*)x{y`8H-=A3zdaK zWT_40qbx+$Io8AF2@Jtq70};zenINHbZ_}ir?EZ*8Q^36T0Vh@8jhkT2GPnkH4Ni@ zRSSk(=VhjEh`;9I#Cl6RO=y*nsU2y?_Y6ggAq~Vg6$uKdq!TqGB)Ch2N+{0qt{z2l zO8&8HGlogVd5Z$P4AVbf+{sa)Wmc@1uOrr%80=QA)>0dUy(Er(C<~!zC;E}lo)b*5 z8>bkgoaF1U$JYfl_7M}38N}^%PTF9flv`=H235`64TbQ#a$0xXdv(Weex`@{@D~s| zEGMeDrTfZAts-*g7G5$v(G8)Gf49NFON|sSbCD*G5-4*< zYznNf8GQF(m_BLv+Pz%=SFqk|xr?-#OTk|CgO2BJ?B&_PNOwlBrpt2Oq}F<_C{A{? zXd|jwdU4TGyfbBsO&kN)RqT@J4Nf#Ym!))bg4D)L6Ju(BA0;AFS~4T{V#4Z4dF@$} zB826>w7nQkkT&`h^SwF42~HVGwmho-GdWdsX1~}~5#EdaGi#!haci>IaLTNc2t56U zxD_-vC6T@j0+4*?&U2Hc?@*{4D}o0K#R(l%x<+nwn4~c9E**rul&34+%35LxDe9ky zzMyG0jm3H(98xnoG&X2Z(wH}gH9Gn^rFZhaifg$hTi`XE>5kp*Vi?g{bJY(%yZ0VH zAd^A6vMmT#EWgmH7pKg$+DD1cJ-pt^a-dkB=6)TGs&iecx0IfEf4GXvfk%`KMZzi` zTFJ^326J?~adZ$C+_qs6E)f5T5~^qtU!Tr*KinVGOLi*3E%Pmt$)KxKF3K-1e`AJr zXJ6ftdi2zL3Ox(Gl3~HhMrsXJK5KuHu9jS)$Abta;?NlzRwvmhZJ0KanU<&^-n3@` z_%D@2b5_&`^qTmss;gTBD<)vEmn&E}uXZOw2XY zPWcgwayZs>O7FDf@))V$`IgrdR!QRV(>BO~UJ>bH!8b#>;_%G;{L%8P47zfi zb5m80VC?AxL{qoBK!_-c`&Vc{w^in@2O=N*91+#AlgO5Iq|6I4 zykB2_{Mejn)VHIvwk)eQde|_)h3`n4LZ^{#pLop%1);90ID2>9Hb)~-CKJNylRqMr zbDEdvPl6*!*hZQ6lQIR7M;qUloD+3pLh%I6`LdV_6N47XS-O%%Y0kP4i%Ku@EZlQ2 z_~ml5ugZcO-!KKc&_}^BG);|eGGfnhL1%qSG173##V?~O^B+jXx=VVWe5jXNL|m3` zKCThJK}712GVCzNnxc3lO{s5f<4dQUfZKiQ>OnXBvLlue&4~XCoAnbGv%6<^Kykd-R@cGlmXWp!{c742i%lW?Kr+|Fp;Qz-jVV^L7x|5XZy zm&`S;NkU9*u#v<*DIYb=YGv1`iQYZ#wvui@ul}sJ<&!Y#7lS2X!XPMqH%?CtoECRY zuE>KzyP6hbHTKaXv#+|lAluY!-}^(sRdae|64j6wdS&$mg=lrNb3zXDLECl}$B-b% z#fELd?lW(awbuJ^`O@l7-xP=V)yPAHf8dM!a2(tx5IeEVg_o*eQ4(eF)X-I;*zqtN zCtgn&q#|B{Fm9Y-qaQS>UpQ&d?pK zzQ*i!Szm_Ft7Cqg;rr?gOoqLm|IGyIgjI7TR{yKot507oSZtA%(mhPw7X4`FwX+|wHt&nmIzt`S6XK3(&& z*HHpe4#7~w;n!;@<|dnkERETgfe)OD$l_6?oZ_TNW|KsmJgPkZ zHC!*FCf`uNvOu95zP(hR{<Kokd>Jv_)^QYwF^#E^qZ72`aB-J5Lq|ZCC$J+KhU- z-!9vr`%K|2a|_zpg`3Xz7Bo8|*l3K1ICyT7ufh8=OnkdLPTGS*E&(ec_mCK_ZOcD@ z#Ec5qt2Wt|p#~7S8^@cI;k9Pkm0dP_omyh!W|UP9ywAOLZ0jvQVsE?W^Pd#Nj5;;# z$!4YeZdz}PPcV^27}`{Q@m%R#mh64f!p}ovUI7jg*%nUa> z?&c3IRt=8jRD08TpSxP{FN_=v{6QfN1H36b@X%WH97)28w{O0#6XecsI1d5PXl*}xe z+#E71o%?<8Xcei(Kb8$avtsvBWeIa%amiekN89;#C@yF#$qtd%OW>JTNvwnC7V!5S zym;a8$?u&o8(U?o2Bo&C(LW+^ZT-L!HgI^y6vMBp?5;UvfZcaCzJMF}lmGjegW*?4 zX!j9~28b48+--rSq@t{EqL)-8*Y+PEPdiCIobsiYzTxNls9{AEu#`A*g>$)$F~fun zRfgd&_GP>&2aoTAfoKUjY=edv zUHOLmC8fnLO3U(s1Bmc#Z#^KXl`}MCeitb4xYNM17>zUI-yG~6XysktuJ7@qxERu^ z7%_&_>++OJ!rsMfBcGTcE|)5ln=q*eD|A`b?fM&^EHl~0zwdK_P3rmPrq`Rwr-L%O zbz!%wJi*2^bn$lGqwGz8;P?`%PUjr|6m59Rx$e4$OnOwIOu&aF&46K>F@{Y$?p9@U z_*T2lUJj)7d%xr&y&RT0gPX$a!5>sbO1S1e!&Lsf_*e)l7L56V%}1N(>KnHcgaXZX z4mq-RfxVKNz5JJU%K2!iT~!quNe;s;7;Wf?h>rLTYRmA#YSEq$6E(0ON8_YkD!+&D z+O!0%OEW-mVi}|oe-uxdZ^IjIR{SJJZ?}y<6XZ8$uLRF_R_Wp*Dt@WU&f-5%x%C)yf*9MQ#3;Y*(x z(Yzfo@V`YlUj8z;__p@Rp>1s-W<;28h0`%zeTGSKz?KNM2*2m{iWfDNWM=!SnJLxO zTC16{OksSAWQ2p~z_@zf*iim!g{9F?M%8L}v9uk>v2IHFlbKt)Nngs|u<_%k1B39l z?dA7lQ#dm1Zr=h=FLMvbka0A)+(nr0_B+eoRc?$%j+pgDU&Hd$K2|ev zZFAa3>b*lCoI-nSbu1sUthl}idWH5(nFY!Bt7@8 zg}5N73My5^N(Gc^doNRqoE=>@{cg^;;w_zVq%djBooYIV@2uDKSSajFHgwUxTqK(a z{2GGxRoh&OU~VU(Cr9+b#wVuC{QK&IuoWrC(3-)9LAwRKw`mO=-D*8Qwji0(rxv)< zG&2!|S!YV~X|N)A_T<{XbooS==L*EIL!Uqg2&&C|(1#}{gk!`=W~dxujj2}2rkjwT zi4Zg&Ra(C_^ff(qaQ{7Rl*0^5C&9XMe$>?u4SBQ3J1^+=`YrDhm-3dmtak)%ekE!%y{Tdncu0B_>U_`Vi z^1#e=b2rR3nMGtSAwntcZRo{gOn!_Qwwi#IpU?Mh;?KQQeyprA_`^N0-ocW!N_pdZ zy?ZW9gQCUWS^;lzl#xmAmDQz5;>|blg^CE*NRGLWRPfQY_sTzc6UcP8;p;214!Ibf zZGDg%%XWpBv--{bA{@Wbl#5Z4^u#efs}v5Btt?x(LH$(2EpY?84}z+c51IeAB#gwG z8CB6an(5mQOu>Dob3Eu#Zaf>Jjw;Ex75A6bp%@RF5$T)Fy@X}huk0+t*r59?_w@K# zrlX@)NStY~WCF^BQ<3%)NSG#(KfmejwfAu1_s7^tMiTIRn52j=EnzM{%Tf9vzn1Gp zl0=aR{j)GfeG!|jXzMGde%2Z!WF2PuBP|*P&bN;boBY)c&5{Iyf{=|xHa`8X0$x;Y ztfVt}ABtg_D#oSkg{JH#P9r4nr1|SE14t05OH(@$!Xw{jpHkmC6PgAq_>~-%=|AXH zR25V=GLSAGB+OW9xPH}rdw7_~v$J0fv6}>S`XM^TXacki*?0oMN52iCS*n@L;B}~V)sM-$+BGo^+m6-r_L`1M z*qMCz(@V42=?a&e1|9{tYb5gdbk{oeN$nv!Axr_CGd#i8vTCUhU&^8m1lSplzgZ@( zD}3$8*chlElu(#Z3sJ-w#w!q!g%&9cx`FvZoKlcZ2Q9+?GMph|m5$;uhdGv%CNK@k z`AfS@-WjUBvGz65;K$$h8{9U*n3uCMhoNt|bW4RTK1t!`Gx8?4&)R{8@N==V$DFh@ z{d0FW&P^$elJxX#UokXs!I#Ckv@I^%4;P(U#J^b#)QW!QoyBDmQERe zzqTgd9mSOt^~I2Nl9^aUQxj&<3ZrplNx@Zt&Q@IYxC7*q^^wv$J<~bWl0drV{qJ&D zRwsg93&CBsOjp-AY|kSBiH0NrEBrR=4p6Aa5(<5>>q|>&=*Wv{H?=Rb)6nTB@&ke8 zoi9;;3!>;`{5+dD)qnJLO|y)@AT>HAe`1M4hQ7K7{p-y7mU$Re8q#Yprq6p^IqfVKubREFtMf`8zn zT70*CvaKn1YB4DiA*Rmj*_?{RuqtqO=`D9)<*@d15A#%pvAK0 zW84#5y_`3);l#u%lK_mv^4vpr|NDw8kQQs0 zRT7;~4y5HD?$Xk3iel5cLd@QpY*#J>mUXSFKUP8ic;^?inCd#8Jm?b>2cl}#Nm=Bs zw47I@H)EPzXV~Mumu-VJHjr_ zbG_$n>VsceURbLu;U*E?(1&ebuo@Y$j)GzdM3dhH$49=3#M-#ur)DI{NcO3-N@-EP z^)rD!?-W2Y^xz>gD`earFNN`_i!Ry)e!i6$EZ_mTw)YmqG`QYoiS=m(h6QyS{tsUAM^ zw7$U)C0e=ojNGDrn^P8Dp4S$QE zx2JQyM@g7tyu*Y@2m(R$I|I`O^fAQ~^Iu zcAc1RQixrd_W^GQA9Y>6?n|KQ!0J?3LMWq&Gdq1%i$EdcNG^XnPUeed{F}*;x?8(&wRNngJ{=D|sF&9mBVUMGV)b)jiDc zagg#i)#Zo!%MM+NNVpcP0KfWF2vuL!nIP2NW3k2BpBbX+HFnY zVMOAB10ie=-D-Wf9p|YE5sZgk814QJb3awSOdsN!lRdobrXv*327k8PTjwRD=TBLS zBhA2>ZbIv@>81T??>8mlnYyrgdN1M~RVY271ajQhA(!}*hJsvbveuWaOzJxPO6pdg z*RD?n&h2Fuw_(FA`_^|%A#sEI<{T)^5eW`klA%t+?)SzVR;~nb@2GSKVzkV?S6{N#PeNvdA_R94>E~)RHlpdnR&vW|IiXH?(kAjiB!Y zv)ZlHt(zE8+@n<5I^9@v(%d&d({omH%#5tI-f>K2l6i|P98Md*q+i2K zTz~2H6=o*69t-CVJ!O&FZjLgLrE!e)+$?pdf_3}Vo3L008Px2Eq$PtT`*IgSfQ_B& z^IcK<@TsaHj;rM|bKgc~#JQ1W{l~skrO%Vn*#6Cl){h1Ri$x9UcLp_eY;!{GfxlwQ zJy8tXyN5}u!=!4>VRHi`-RcX3kp?aj?cVb>tb|$%W6W6Pex+`x=`)fuayKWt`^CZ` zR>HbaW*d=IWE@!SNBP%fbr|Sud1U(I zSdmwrZ$dL?WSg)wbiL6rS|az;t#Z0(vrCzKqV9f5GUDmfUEJ?(@6EV`$|Q9Z)p=xJ5hhdwKr>vP0OG2vcyjlSY+ zjq%{5v3-H!)<_z!$=9jFVZ%}QUtT7nM1StTH0DH5s;aCsv|)ewcqvhgY=SCV{heML zMX25($S-);aN4Hcsfd+ zfpeL)jjE|t185$-vM?`nm7gm(Yk%1ZgA9TB$N2msMiqQ7;jNU=komBeqNsaCTF&W@ z4!=w1N4Lb84T-1rD#+yaQ|WLetbkD3$SHK;B%x&FfR;o01omwuF=$nzT+t}!V-`|v z9JoU6eU@*k0Rl}}v^7YT7nf_a=8!Z;^7CG2NZRr9D%9J!FF7+#T4!rx(`+JYH;Ff9 zMs15GArR$6-QIo92%{x{CLx;1LZS^tF41;Oe21X8rDYZyGKV#Xf{a%93XS7ovcH)D zdMUs52(u7wmtahFzBA-@r~&S0*BB)oSrX$?CA-p3OlPc%nUpZXF3d4QEvm(cW@X;K z;6vSn3O-?FB&38`%-4aPq*zefjqPjVG~=UYX*VUOaRMwxSR+|??Ovzs4l+oDojCym z5vH+1uzF+SL#$pe7)u-NI?H$AV!nHvVrkd+kLnH}c6bOKnEVP82xz3&Vt=})XY@hq z`29PzA97u+s|b;p#)ks2tr%6K_omHE^S6G%&gG&0C%L+lI;-3VN65pv*ia>PO3Tc7 zn}(Ibl9ADZ4|!GI8E8saDWY5JY7Z;SB%c?TGnS0uHHUr1RafR65H}E$ea;5$&RFi# zh~p8E$}f!pJlPIi;ZJN0euA8+I`o^=0+prj{j2jkXdH)kwnvZe!&jA3`7%z(^38Ey zVf&eC5_`l)$mTJ#NMT7he`muVTH>o3=b{;p{0bcrk?TYl^bVHJf40gZ!2xP1e^Wk? zi6v;S_YjKw1p?_s2$iul%}u^DE7dRY;ORSQJ4P~XU?H|w-0k`DE%A`8q4#KeI9;eY zFGgfs+p~=~3C>IR?7`I2&G+i}j`*1}+GaEljnI~dVOXjX8E)w*EMe!!I=Rl_>O(WP zynRprEYlYz!UvlVTSWmim@GcA)TUd9HllV?wXUtOBOc8XFttHR8hJE9%WE~#*D|R-1mpI_ zbv#!IdRui!Rc=f@T71~%wdR!<-Uj8)o(&GdPvz2-w!3`Iv`>{TX*V_KjXy#g42XUC z>WowrAW*X~H#M3*0J1>E>yn1_@A6k~RmO5m)53M!6I*%pFp$NgTgv**w;iDxiFvEw z24PRRdt`@y+xr>8)sdtL!+Xxe8S+1AxS;r+AI2CEfMnup`7$2rSMAuVy4 z&VGU9YrIleX$roS=ze-XQp!EY#DS*suOBYnFbyqb-g`|lcVCUN#vgbh63-6bd$sK$ zQz@Rpmg6i6A$S-DVOiugDvE!(*hYu@7&0qLljmFEawL)$=khAv2=`)9(Rn;1uU3YL zI9)_mbFX1sAR^9a^=5OS?fjJ#AxoKbjPApiV4uJT%{h$D@YlbQ^(n*s$bzkRdDs(s z*?5Oc;EyyqXjUlVS$BuBM!dS(I&L;_h2N1B`p#U@!}hRurA{|@&7qfC+w~DdxRvMr zDAkD%G&HLuQ=D#09QhIQ&8d|)!U9F)hl}>(7R4zNT$6-XM)#uc{M!{1*heF|qF2OJ zMX&OCg{}v9URU{7OtPs+gx9Eu*)3vTJn7A8_svx_i|xI2e|N&+9f{sgcbK*KmLy0=eGEtI z{C0y3)FI|hHlMa`LFR}yVGu2WaD)=+R#eSR5&J(*M@LKK=?0WahvbHa*c{Fo_)tVnv%PvuS8KLEdi1haz`&L5cx%|;(}X^0E6 zMTxshjoXPFR%|S;G&Y7mt!4PcStovgBsvrT12ct>6s~FrX=-N`{!7#xyCB}{qcrLi z3zSAXx~sBt^at4Vudp>dug7L+AePsZ+5aa9`7@gO561c55OVfsg!TVN5b`(AjRO#J z4)6{s*Ym~x6G9Fy@c##d{Qo^J9DK|Fg$rk6=ls9m!m~67V;3cHLj;7QFFN!UQ*>&e z%bQo?Bsg=pH%(cD(UEFdYvQTuGrv;S)AgfNnP*lFH4K%KM-AuGsuFVVQrii zqsCKvSoyEp%MCPss)J%8$DUA=%K>TQ^!PVH?q4*PgpyjXHQ60C4jk&Vb!2Ia2+0{) zQ_>yk%W_jYM|Bk|COCbcWb!enL>=uHH+pxzsr92uGEk`X->dX1qW=t5q!PN+)MwU_ zdPFKWsJ=6SgLF9Pj2@qFw>a@DuD!&`#HnRCAvqwOLqFL%`Z(ETj3H!Gxia&Kchle| z`aKdy8nx(@&i67LuFIGi9m%ZfO4oX7+08(sLAvk=-@eS^F|KU@(N_8!JUAKC1xYnduW$s?E>cof zS_pZZg$H6l`Ehp4qraDIe82HCIFPz|)BH0`!bHy9e4*b?mnBUBB2-w6X|)&z0}RrP zKbH=KyjF>=C*~)iVj^lD$E*&G6U+gZO_or2kEnSR5(UN2K6}x8m(xjqDRcuHw>5zYwk|K1Z($F(WQnj$Qh z4e!NkmSQHZTO^u8+pUfTPn=b1x8?EcRi{d^Qs=3gEYkvn#RBT!BXcJD5Zy!%uN(c% zEW%H8*)$w;tyA?C$I9@Ho+ks(-X;oloj2Hdwdp@#7gA4XWvG8)F(}oE6R7oKotSb7 zjIE8xe}GF(WLYH%6VG*yXKywmElOyxl%` zQma^8_I>NeG;_-f(NzHDfhVD3VpqFEG?FAaRCjJW3xrO}ghOjw6X&bbM4WDfB6g^= zdf^gnz|;}6Lx4&q9Ri1%6GI~$A0%--K-CQ?u8iG1-pZv-)W><0jMt;0vy;D}EDb-e zR&7AkK`5X?G=Q<5OoZ(_!j(ax0^tVDnL(=~ODxg8_u2P=u>gUC+}8@RqwzBDy=n}z zFw1dia!qM99n9tjICJlg6=cMyV-dp=xbE?>q`)G#($wf<$GGDr((<}fnW{;e;u=}L zcv6&U6k9>$Cq0eE+HlV!m6A5TVAB)kz5PK8C$poa?*#-PV&cex8~x?rEp!a z?CA`vrk6IT6AHG=>;Cj^gTp(691eZvhSyM?ID@~-=*!=a>7)*W03glHqu}axn6)SE zfZl_8rADtciMz!8qeE)%cIIkiqYX_}Nd*GoI#1zbM zGMYlth(risE(Dv0Y*Bvpd$WsvY;Nn8=CQ+Grl+Yx%2US7l-~3EX*Ow~C(NF#-@;mZ z1L5&F(I;b~(>T?-G^oum+{aN5l$^B%cON*74y)yGeX7TL4ybNw;n(?S0XPe9;3BmU z)Fu<{vE)L@50QV;mQ41wrO~_4hnwd`Wf`F)3@#k704LRrkj8`C3{0>f031zOroOC$$caK@Zog#{`yb*+`THMNn0S6>&JT)R= z;!@5QqdWuuM&}Ury2r8VM#qP($cUUqx}A<_5^sLF!$|Kp$G8ynYiu|`TJ@J{qKf9e zm%@%{ay2okeCYk-Q)}2a!bSMf`*gpyN+@@CgLAgz&V#%oFp198FQ~*IB73aU-{lZP zu^^~)YY|pOkU>bCl*kCUh|V>>!Sc;S3P~7686-}Rk00*T$U#Hip&;YuB2tP_A&=YO z_*Vb8#-E89Hy%Q76xv<;l25#>5t6g9_wKNdLO{np4XP)F7larE=|rc=wq z+|0gt(<;;TC;3v6lr%Pl;i|aX&7wvfyv9e!4H5&J-NNRn(O?=>sz|4}`4|QJxa;d} z!6B|TXNy7KcQ{AZ26pFRE!$+r4Q3yET|XA=|N10<-|@-0Cg*nto1!PQvysJ!8oZi7 zO324{gO}6h^cK9-WA%833|bHS+X%&uXT^G;lus2;`+8Y|LB9>9*EE=v(e;?JKVE2^nd()SU3m)tMD>NvLsfBr+-ta3e%T=Fa2h% zY-y#F=f*eoxbQ&>t2OCp?U?u-;fV2e4)$e1LK|9P<-3UnO{qfPMzFkZPdBSvInNEZU!Hn)9{%{G#)j$gt8hd{j9w0;JpBLNxX^&io z9c5pUVnz?~8A$Fj2 zX@LDig)+>4@~5@ymqm%zk@B*N%Jfp~+#cxiOF zNpH|=Ye`^aR=Eq$L;staX^vyqG3HIeA9*nR~9eSDv-bnl0b=8-32FIzRfFLh@~44dIvF zM1bv7pasvwKunMlqM?t#ITCQT!ZZjNy8KDOX@;_6;64!uC;RV1R8#GUWUXC<5UvKi zD3v;>1u!ZjPN)??z+HbKSh;;7KOmoB-UVb)3~2fqKiCq8Y>+JUEk1|Mc~Uz{jNpCH zvxSD;R>!cJ30mGGVafA|bT2-)Qy*Y&&ToWEw`IE&xf;2g(Z^-GOH6)~im6R68?!YANBd+APKE<6X7ks^~D!*0a0(5bAWKL<^9&vt!+0w)`lgH(y zqVym#l;o9^k+pwkJZ&puT&=S z7-PiopA-~@;}lWXiIYmtTHaSZOOO)>ZkxmN{0qPJ0-JVq3i=~LZ6AQ0erJv8Xo^s8 zi6UFHT9}SwJ5k$YY1?2s@m%YJ_AlSbUwyY2(-y}Gg)=Ok&m$R|u2~%(Q3hO4fp5to zH0Io%!_Zr9(HU^8QtZyeWAUK_@&v+V|RuNQHTY}UKi0pMc#^9bD)-%R)!?y zDCH3Te5hsR6uvRykOAa-v$thtmdKEF)hoByV16p)Ee6GF@F<%y5n+!!lAENV&t*~i z9g3FvyoH9|M=T08y;ge*Rf59M#}|Y<-w1RTkC5Ew3rhfSOh$eu3FrAczS7_JWe2wOfUlZ9k}Qa z5A?x4AsV@@X|%yUmQ8nzVPu?zM@aMn^tP9K?#)Xz5N8RV1zw^n7GeZ?t96VpXn-;$ z3oP_ljzH9bH5w%IAsv)HX^Hlir=R}c+mg-W-4`5VzHik*DNF~rr%&$L3+h;}s@per z3vi6ngIsOvnFn%U0^>#paD4s25UOoG8~dqv;DwWb&Kr6gOPf)g-ARSz^yl}<9Spei zrtlq%M#q5_O^oyEPvj%m=>zs6;ReoXDs~93{TOoU=05jHEeL%_?h~kXlil_b$_jYv z@kz-gx|7@X?qZ|aEtYU05f+m{EtCju&DK^7y3)!xy@ajy4qV^EgMU!8)_1Dz0QzB@ z^k(>%rS5vq0s&sYV1pgUXrmS1O?dDbcp%9%mnf{9R_~P@A_EaAXgs(~gKHJ1I=WuQ zPY?%!%u1h)+GCI#`Foq`CBktD8f~44NF#)kOo)#ty&bS>%pvwQ+5dGiZw?RrgZ3dTB`WO>!mlJQ*6^e62rz>YgHIbj4p9&0A1}+qUNv?Md&Ep+Pr=T%esFSy0TGPU z)_5@{iC7OlP9fS#FINO1G~tfB@JmI zLrq$HhB#*&#%*$;oKQNbh~BuDeGrOgM1AHtPbLbF1?tB8$*lkiA*CGqB>5KTvmnWOx2K?P0wxcgkQA@i8$OPPMljxCBD} zR3JGIHWUC~UY;z-)DRN%l(bR(n-B%Z_Hplo%IJfCjHuza8Mi$SD~3cjVaRnx&Z;dZ zI2VIdELLx+-S&8yBS5dbs?|d&sqaW(dizEdKhvD|c2cN8TC`&eQ3Ps5*I3&2p&l>L z*?*ScFL=DQtj~v-c`TkbdRR7Tb+Ekftkj=`gmA%Mymt=w&B_*w8=$jUliKdy2+Ljw zEj-@ZV%VmHq?kQPD0jLqSFGTtuMu7lk6mOuFQj<3J;$RLD}NO~xf?CjYtrA?Lll1i zO2h>5#0sr$c;Gh>Zu9b#nM#3s;aO$Pkl(H05r_9Ksk*UlIcw-5><=y)1PKTb_7jK_ z>3Kew79f%xK|BM=UH(@7?9K+-R!rTfxQ?&zEufjf1M?9~gAJEGL4$QH``JT< zB_OLXk*k5cc?>~`Lm=* z60+N3MZ(U|W~q%JeAYq*B6y%Xk*6cKq=+)Lf`>9Fd#fdnu=#8GzCJ3J5W)CZDm*wF z4C!~4gQvt*>f;i{^O1U0)er1T1Bel>xz&=22gYIj3PbJ za-iT7`8ova0P*`G4X6xPUP5F?Ny18)%1^niYc&sso$6j}>MEIYBGEX@48yppgzT;z z&61#5Gk>T#IJ4xQtWt$=*=C-nWzaa~!VbUe5A0zo2H)D78kWqO<4pA0_G)|3bYCSi zg;SHjBG)weBw!T-lzx)z02CVFWKk$3j<%<*7_-VfV$NS(JsA$zD?DtmRjUb5g2*`U z9x%Oc%y)s_Zx*>ZaX}0*0A9 z88xg9^bB&nZ!Fy1bJ6-pPM&6Gr;MAuP|6jg))e~O)5i!(86eGyKDyLR>T7}WG8aa% zg@lx07jyA+t}Hl6=!Z&MZnc!;IR>m;g=wirXkAY5baw*1q=~{NW&0^KY5uDt{xja!T zN08-SZ0At#TXKW265%qwyVx)h;atX#`s9~yBMaAn7Ifr50h_q(1n#Wc&j>p=$?~3gcVe3OM#$w5Y&Bg^DzFUq%42n9IbLXSZ!SuV~ z(_zQe8xJz}bQzXP)+v#riLQ{N>^ zbq{apHBPz&-uTGSK7)-9j;I6~>3oNYqbP27daM_~izsmKFvM_5&_O$RN!jU9WF;6Kv;-Ufs!)kBa^v%1!Ml?naL2eW6LM^vgVWiLhdU(y~ z;nJDMToH0dDTC)_*Pj_yNlK>+C@+9?nldRG+XLTrx`!N^C1Fq5N1$joY464b z2yY+j?K}SocC0(`( z@y4HDJFPr-2Pz2I1d$dWL@T{;=*?KR+0zQ@usHV+@je}6C!ZT@qxpSy*zwBx zygfV`6FttG>xKUIm);F1`NmA@Mk$|IDgjX7o566K61jM?l%3=fmNCo%IaipL=FM@E=I9;7OF&4`(6 z1)N!wFwruRV4F?C@KCkw8`H``86mf?ZRjvmECkk`e?4k51e1^VVhsFYT2Fem##nM^3uIM>u&!|Ni4y{9R-rjYV3zjyaB9ArhkfYR0*JtASc#+arB5*uX ziazaxB7#MvX@7sViMZ92|89ES9zI&Gptb^%{?SE$ztG7HZN zj0?G1^vp~w0CW19$@C1v`h|xp8p2-22=);TF=zuYy ziMnhYZg*-WTuBs%?(0HjwORiZq2LkK5*Z0%^*KN-J2KWjLDaq4ifnvwOB!)16x&98 z0+JwCYAwwD5WT}eW%s<~PQdZ|R|T8)i|e1?Y4qawFNXzduSLqA$8ZBaZ}QYModp`t zLthqnvu*jke#FoH4j#*)!ud-dSRMWk}w{KIeNQ;i2H$RZr}~ zC4#{>+i$2{nC75T7eP0eLU~t-c6#Q?tB;m_>#gZ7u+0}a;e%-?kk9{}=RHT0*~V{! zjeFO-@(YQy(rgG>wA~1Y)tkHrHonRl`1G9wYJ_CAj{KwhL(6i~*U2*R+%LwA-`caD zvXc2o<8*F2lslx_Wc=4ZE6ADj9x(=a+nP+lMhazsQc4OZcAbgnE~qA+-L9j!Xj@ns zE=3q=Cr}1Xbh6!3F_L7C*7q9?%jwawApU?JAmzS#4o+`9Im&R=KD-?fh0{uW+huOX zJ+-JGlm;BGbc!n?DNwJ%*iyOkxSxc5yiQIHqn3*l;>Tv_BZPtUe}Ax*o>k!wInvd{ zf$U)6V|(atY=%z|pgJ2=9X+RE?ueClo7;z@-)z05E`{R^ui` zvY%B!VW9n*A&oh#0f<=%gVpSpt34&!pZka!(Y|Td&I`}@x)PTkSx49$B()!mZ#{opq4DP(1&kx|MIuv)8`x1mZ z?DVOtT0|ZSec#^iR^WXeV>Dzdbv(aAntgK}Pc1 z7;~z<#Nv7nKn^1FGyRJM33Z&WB)Yk3l)R!e0N%O}$OMRvol?EhoQpwvR%Et9x%`}g zRO(8?Fhj8uC1Uh9WA;F;g~*pRVjE2{9?3gN<0sG#;|Feem!)9N&uv3*-=r^Z%v7Y4 z@I33aA?$Np#)`~4^a_D#axkr)r1EVmBo+lQj)}(lrmeu)5Q5X=&$4N11T_fptv^W} zU0pHIQ8=4#|kq^Om)E6ws;^2w8@G#W%B%k;+viC zF_m+;7-xC}nm4MeWN6814Z1-}y&!yt`BqJAT;LDL+z!2Id4JOJND20?MfvI5AQIPO z{h#zVKP|5!X-3q zFKI4@a{v*1Zocy!mXDFeVP!Xc@C-c;(d&&jih^I~R~h^nKLI-`-x%ZtCslc9@j2)Zks&Lu%TJC8^GPY`zSdxxdz#4>Q zB=`>zW6BT5(Iu%PGIHYuT?rmt5*iAeM_KD~0bZAobTJv_88{c=J5aP6Jqd|<4J~?K z_dpZTpV>8f@~X48J~g!a0XS&E_tL5X$5yN|thOhMO>M`AkZHjO#s+% zdp!A0g}9tgyj)uI;a*ZX-Sv8N6?>Anu;rN3hQP!r5<}|T6Vzp+y97k@`^`K^3jwp7 zPrWS6N@7JrxB3eXBr_nGK&pTQ87J2%H~UwnQD9MWw8(LzH(u}rB=(8hs*Gq_>J#mm ziAMM@nmNJ=nupX38Pb7ocxRw~4DE^s_(bXWvr+%fFg;Up?{WP&#UXEmRq=~d;A<@m zrD&0ndxJE9+N_#WzdnpX(8qJEPn{6m;l|y2FuwgXzNp^CSWGJ{-gzQd3#iLf&SW>O zpk_lm&vv9F@NTcYC-ARetR9%;TMr7!E3S_U=rJM3MbTA{?<>(G42!6PgS^Ai>DC!5 zOr>Nq2{JkNd!O+}*Y=-a+jB&HDh{_|mm*n+W)~#$XzuN;FedzHB*w)+nGE%Hi&~_C zLAJI)P&NVcTX?=}>aL|YtY&8gD@3hq-&FFbWjr2YPn3d;rrv+K45;g6%(d&jBsIr9 zitiSW(k$?4u z{NoW>Qhpfyz;xB$3FX$wc2R2ZFjjy=lPNP9x^95cDr+zOYuqxOFn6>Bbe&)QJk- za1r>s6h!3rc1m5i_D#yh&b{s zIC}P^+oK)HOsSiKNRo$@UQdM_T}dWVeM_-H2LDdK@5*Wp;o{vLyoEg&aW_t8GTPBj zNmZ(Jv(SD%#~~%q`AOG|!_bD%;@LSXRLD%lnIqP{-!z8&Ft`AnC(uQ>*+JIAZNER& zlNjn73Zj65M1jqiR+ZTdjGX2-Bx;O$3z_kKx5>FY(Gy41VEw@3=2S+na1NxFg`1oa z*Sni&d+N%E6<5{DQkMoozv0x+CShQyMzsR4Pwllq!3l&xp_4O@W2v8!z<5*@7k(Ib z=#mfQR)DZ|q&Ff3)d>}e4Sq*;H2avR{3_p{^nHH&*}>y0lyRZl_}&n;3Q1$c>}qp+Jm{1lm=jXGVQnXpLbJ1Nw>5i1TuYGe zi%wEmh^TNHrzkB~z$ZE7t_-YGzjBWXC~!tflJ9U5sOw9&vu^O_GX_d{HAo)J@lO;W zNVh!bQtb*dE@vY3kwVCJ10v{Eo!~l_*c#rN3GtEqjWK7(fb}Tp25n(X1is#y^P?_d z$ZZ*Y4*9|kn)9s1I3dC}{rK)Td~r`e6ZKWZi2*DT-M+_;5AC|V_4uW_ZJw*|?VR3l z5Ljyd5l#HbZD8UVB#>hYq(1K0!%(ETz$Eq9Tu4;~m!ho_N}0F<$!%4$zvv9U7vsojCDP@szwG1hcoH&%T3I%O@xo!zdj zWgxT?4Cd+ytj*gM`Xi{mUYg$R&t$l{0mq0Nbz^dnhyB=uUdsV(Qrdz7zm`7ge<>zj zg*(8&?fyDv8U2%K{!{9?Os?)Q)@{xw&!{-1)^9y}>Ru?^rOV?#-)f{jo#}7_eth#h z0g9nFlmFh34A=ytdLVQ+zyS>6ysAM2R3e5T^*o-Feb!1ogq1yDmJ0RXR)aUz7&p=_Q>v6c-n;_0RZ%V)Vwe+{W(yg+tx-hSoa zY35*qr~Z@T(J%+I2?aFFGlNS6Akv!ojruLu(I_M6beHuO3({5_>kRE8`cz-&n zAF*I{yx{E&3oyzh{-3&`zhkdbG4clME{;@4$l}*T0EtgvPNAY?RYwHYFZZQ5oGJx1 z90E____fX>S3@`SMP6}0fzgSwIRhR^WRgMRh0uXZeW4>Z&h%mh(al*m7f5m0g&`P9 zt=t?5q1y_Qp&JUIGZnTGzH}fL%az_Jl{w6Z*z&p{^)&O3o2_k+xIZ!YP#k|ONpMU`f1LDRR$abKB zPKHrd7@mfOO(3f+E&j*MTF&o-p3Wf*@n)6HNW9LDf^?n=pnk7QU>y43yw66%U*P9< zu7~B1`G%eipmExV}j@v~AE49F(qg zK7VaLTB)O6n0s?=D3#EmQxD;lR`NXfNEy`2L@D^@I}`(h?X=N}E>T($Z&g#e;n%c|r!(DR4s8$lPFS^rCX& zcv2(nQg8c0s(s>!B`hTqzD#fP9-3N@;nNp!A{I9 z5N9c+JSKa=rT7~)FSs@tTI<3ihbQCc{khGG9_?+@UD}hh&@+?AwE=J*Cm^i>tsT$I zX3it_eL?&p7-9$BG|+xXQW{nuGdk#12}GjdDHkaz?ns-`DVT&5YQT-Ov0gT90A>}d zO)P8WAa)*BUND3U@N3WR{eoI**viB$Zm@s*|cl`n{lAfI*u}#1|(ScYfRuG$<^@CVVaC3l~SYVw4p_P54dRD9yX_XX9 z7IC!t5=4s#u7}l0X#!~9QrXbceDb*B#)=WUH3}7vO6M4Ok3*@Q6pw6AmhejFaHnHb zJq*OMlh8`f(=~+*v5`)Ym~CpV31}kz%Y|yOjk~Q+=tq+{-2iBtBD`>gi{Vyka&o;+X{Rio z$BW6)B<96B_hE86L_QKmFaar>XCt27AY&2(-#EbymEVE%4n;c4x{8vO8s#;RYA-|Z zgOuVsKIY#YLdh$@`3yo~sH?(ZUGYArUOiis#Qf=Zv2+))ZpA?q_aBtl`v zagbH^C`x=q4q+CY1=ELR*AK`$pLM_b3Q+0@aBDvbbViowRu|N*jUoEtoB6rTt1VUl zj;{)?%(10REoVg^e$TUQ>Fi{$)4SP{|2$`O!cjZr<=D5yivO&-l1=_>^2~U$CdIK1 zB5KGCS}*iaR?@8WY`?jS&TVpKPWWYO!Rn{Cz0-|~%}DLJhUc#nr-l9`yV$eC-Ks<2 zsn1)MQ3HwOX3(ZX&L60-ssEyiPWa_(i4kacPeHz4@Q;Hrlrrd$2y=roIc<+K83&{< z+HK#jha?;*G;*-sXCy_bT>Ls$lyfp|etr~5f|rb1BzRuUri6ob{cFp<_g4+3r+Ews z4<%LNV!?ilaAciQXJd3>g9ZSzaz>K~gEAtNo8Y|&xWq6CPB1I_m<;H=RTbtFPe9hX zMgz&X#Xdoxxek(t$jcppFsl;COM<9}MY2d-AE*8uLB3Uz5y2W6^Kig^0XvZFbF;kB zP#GTr9Ozq$2ui7457gEr4NJC%->5?ftY`Ac?exYSJgB|}OiyK3!AvNEe|m(@+%o>R zX^Ysc!kw+FBt(y@i%S4Jt)zfyy@yA4v?OKFx?bnLXGE#Io>~2z(N=4Lxgz$^UM2p) zoLp6cM{QsG%OZdu&ux$w2Lb> z$n@N0D&_OO=8QLW?V>phf!i6ov?I7M;w0;x*!T0ECWJoA$$4SPc^(Sq_C=bCS^t{V{k!9ufc^J~>^~c=fBnM$AC1-@Gr<2ji~Hk}g@E;U=lB2n_Um7$ z{Y(2bD+d$nf9bydqCOtK(+pd=yC}a^kY)9WB>tIOj)^;MskG(PT{$Uz#J|xZW2JUB zZrAle`y5$DkCZ?_!MVx2skQVCu<#KW2;a}`=W9AG+|JqtyW0ideuQ<+(#D*mu37}j zI|Qm~e0aN7q7n%aJ$lBBZg}6)HsF-m!MpBxC+%lXUzR}LG}|9GFSS%EO0*a1KbKy; z)k$2wLcI?4$(V(e112J|xF|N8ru19gtYo|~YxYEzN5fy*e2l5Fs$kMEwG7U~SHm3B ztL(~XG<+*K8e=&ezQ-*q+A$a~=AWz~#*}OcyR)+D^!qd$@CO! zT!9sf2{wIuS`CvppZLa#XL!TD=<*2+gW?B? zK3fs?+3t9%pITUN@;sC^YJZoFDG`O2{& zAGDrUDT(%dmSJ%l9u0rFNmR^9!~T;+lPgpLM&$j}(gpXLY%}~Zof!Wntzvp~tFerk z@vv*0?&4t!&Dz>j_7`)nc$j+;;`r}k&d?n%#X~)HM8hDh811*$^b-dGH{Ze%f5c?A z%|{Z$N@FEUQc3R(vfCb3e2T!qDU)!5z`0zgRXbeXx5`-HqjP+uRRPxL z3u;4##8j=n5t6RtdbOVt*wr&$?0_reh2exNU2@n~QptD`T~bUKoIgqic87G;;$uDr z+c_Lb&TXDklhG0~nh{6T5!?*oSe^>h0D$W@VJlZeb|VFw=jD|H&@yOM)rg3_HvtZJDD>x`MI)FM7j^0&0QRAR}mQ0`F=XL5Zu z9=rG_^gao%q3=B#Gcxng_IDx@cjCADiJMeVW~Cx?9%8pK(L&guGqH;on6fvS9H_B< zCX#UxRF0_>tV2RTbDr~JJRbvQ9~Y0W3N^WoHlF>11ljL-YE6KFCQKF=0UyIP(7V{V z@>{NWnp0w3(kL!T#cr^Px(aN)vU|U4e&V(VSrfU&tKDfQ>!34iMeg;*#_xrZe-usP zf`VrhuWf?brbx*fvpx~Mg$-~*iN(n$I6dCU1?z?QsB9$6!C;#QBW5EKL#bk2LW>CW zhRYYNqamvDyAsS>pfQTc`Kt*BP8*rZ4^hE@TCbIlzSZXZuxw0>j%H6Y zl}GdYz+l7MZHf?d@RCg8Sg@LNVhiqdY$FR8yI2LK368k3+6kT~qAyxxv;>OO23t%i z;foLYWn4F^l(V~Y*C$o_o$WtONp-Ovo9LO|3o{f-gTVks($XeW_mx&sT$~^IJOazpF=E^_!)O}VG8)8}IVIrmR zZg7Xw>I)T@5Lm#uq`T3`=Dz+T!Ca?H&{$De|Bn2QL4`d`Qm45Pbj}<``z-*K7YcpF zpg6xe#5FJq80gBFkC4%c@YIY1IpcqY8%m)^$8b`b4V)avtVg zxmGN#ynXW)KpNhz+85a86W4U^-mi8gUxnZAGB1AB)9~LQ4v2Tp4N`QbW2yC<6sRlK z5Jt`)ztFt>B9(CKY#dnN@n-P-R^jNLZaiC_qD}A2>mULjE2q2;-OwChXB+Dnbj!&I zBljF$bkW@x)Y({KW~pHzj>^`m9S9rcyVHqyEi7^Nw^wrB0-Hsvs)~Y;7I2%FY0av! z=^$XDPlUns&n7Q7hZ;dFH}53MPTSS?s@?FzU=)(W^*W)gj-pawiMne>7=&eo6ofIM zT4Z0PDKu=F5%Ou_4VW(TUY@$i?A?;WX)2NS(-o5DR^6g$lxuSVz()n^1+jMS3VZJ7{8U~?&Y;{!4s6L}oF5HURB39C0wO2!$j6s05SG9do!}6LArVur#j4o5p}FA`=r*^VMM^1f z<9cUG+WDYH7H2!Mcdrr22$6KHdd5MWqat(wk5q!H-nL&=+IAGwN<0JuoH_|OCop`O z%wT#m89~U79?ncEWn#tbu1XJ3gQT^iuW^mQuOwl8t1=6U-0ZtuHzBG~s&YMq_}y{Y z>75iXXE>6_C|H{}D)RK#6ueMi6`!C1sCmbNkq)erJ0?zxWZ;e;EF zh`)$`{UaxgZ|%|j%Rr(y&mGs>{2VyncF(jZA+dO%R>TN3q7?~aiaH!$PvSeyzCfa& z{{Rv~@6OM(s@ksuNhHtY$Zr(li%@f9Nq9YG9jWI4Mcicjl3=WA1SDd$Tdn-Aou;)^ zWl|BQr+T3nc=l#zBYV4&LsRwB_=KCEW?0kN;9%&9haZ~CUDDxrHoIaJK)uAFC?4|| z$nUWQ+=vR{#soT_WSq6ynoNsm#z=rQy2Od|joP?p5xDCY`-PcToZUDac`;Vr$XE)) zj}BaxhBUNZLZ(a5{=k|jeDqWVe@LBWLw z9us>c=$E$hOm^(uaU2>VUU<+7ldK27R$lHu*RxF;YunBQ+G%EMdu%0}^?%Y@$(Qm* zb65{=RJ~6n0G(kGxZ+6ctjfdts^+Ch?-(>+y8A@73OV3hUd+shUnnZJDNK@=BSPaX z7*sSTKGRjn|GAATEo)r9^1_zevL=W>@-egSFd^2To`Z0x5f+|sBrt9)82 zo43VSKlm@D8X`n<)5*13de(ivc zj!97~QP^}XrnEefPi=H?0eQfZ4_mozyYfDn_1Hd?rtQFILPSBJ3Ma(gfnpemQC*j5 zwkYl(D)XygbT?^40#QpdA>!y+6Z6Hc)=|R2RG*%j%bD06biOXd928>gcUa*rqym<} ze-#B}KDG0oy(vJhBl~9VpZa}kcwEGup%8*cfbf+CkP@?>YdCUf(_RX+&{Dt$j|o;CPm%76 zHtC*c4I(D20qp5Eqq9fi_tf~5()MDk-QYIvepQ5$CI?>b3achnS}OGtj} zF8@(3wK`kDUrhl#04m-rdiHInlFTbHd^piMydJOl#`_H-?Tm~L%(h)7g8Z;@K=y0v z^j%mQh|m#LO}yl1m1yu}U&&I_>(k`1Q!m9V*E#HpWN3GPHmqp2EB|K~w}gqY>#d%O zoVJpx0Ub%WRI{ZR+592&xbgf7knPNs_Adq2dSt{rO;cSzgxO$Ho&du%SDu2wvpMbU z<(Ek0F(N_$A*|zN7M~{$A_U~L)pJZ;3(!eQl3tU)uf4M}5Ak^a0t5UOUz|{6RH#4J@TICL=J0sMsU~013 zSHtBzg5kRk7;xWOpu;eJ4SPx3_85__&&p4+J}`aJtIK_!V(+$S)-!^<)>>D?X-w^&p^@ z>?zSdF128m1pnBHy&!(F+>#VOx}K_h{+pcRa9}AMxzkAZ8FLpWVjm<#T@*#8z~b77 zz=^(%=#Cx)6QK;|y}Ny=n`!l)j&GbagWY67l zQTZVZq~$Fk5YZiDRKm?}A^!lv67wn`LR)HZsQt}@J2t8Z{F0$jV-l|S+0SmeO1LK5 zC-ly5nF;Argu7$TUFxyIF5x^k0a^(?kX4t!ZCe)MNzdo2viSsjBilz+nGGFobB6&fbk2JT*v+OgML*aQjdnlDBv`b?qpC_rePUB?v!`nFUNw zfb)k7&C$g!Owgq&Ecm|60;0Oyk8(Q68&TCF{t&5STAKPCZv^3eu0vqFSA9XmBm#TG zv61^URUkmDB!05ZbgJYMf@HH|2jsACtyCMWnWI~K)DJiN7L?JG ztsLRhbhs?ZZkmM_;l0K+Y7*UI22ex+z8WdpaMhb-4Y8?O`dq9#Ab#8pF@%iQE=r5Z z36sh7N(kphj*@+Y9SwaK>X5m3(2UR-4ZYJ$Y~G!4OgPS-R(IZ{C_`wn_R8ZyGvAQW zXc@eGAgV<>gUS#nzSeKkQs4F}L!PC4AqFEf8Tf@Rrw-2;0AEPPHUq_o&PzwABqz7+ zT!kOY6O~L$Nk-=D!ir_vkBkw`jk4rA4N{Mp7?cO~(p7XioaiLPL3_>_bU^f*=u#8wJ!5vy%-IwFEz76t_?D~v*s@*L;kC!rD1B_o z<04);taA0baaet9y#f`G7jT$>+|e6?F>G*L)S!)u@33j&u-Z5jUjKp`GdcfI+5e1?7?U4@=vP@0%=m$u7`x$00-YL zSU}g);`f1tSux4>4*7t6(Uk$A1$HEW7a63Ix;eE>Gx2zO?piK0_-2R^jJNq+-F~&O zfkkqKMBM-aaGT)_oGRH8b%n`vt?+E+5v>!{JWM*nR+zv+I&-$+6{qXq&Py}@N?~qm ze8KaseW}uXPstA4qGxIN0*h%tQ_Kn#g?SuMGuw43EdD0`2Uj649S~JyZgsa|Q%iQp zq5gO1$0$hSABH5KyCJab#z;uv3i8G^(*eEOQC@ruZvh?(o_9<1)@)0q(sX^yR}aRH zaGScy)MJtjWHKfoVlY7>hgDJa==MX^f?44e+3-W!7J!yDqdPe9W@NVg$mFSV6e_f0 zTm`sei)F6qHfi#%+5G~wzJ3OK-S>ayuUlnP^o1=|E<)QUxc}l`X%+|4NQ%jlwC=+X zD9Bim4|<5EdbDI~bZgQ?gSLmQ)OkqDQVnQ(i=sY)VUsVhvwpwp_8 zi%<(3tdw-egSc9R%}aan;pqDSUZPIF{>OsCFQ3c59)tfbAc)$2I8j>Kn$wF|nwgn? zcz%8uc4{-y8yg!s+S&g3*#DO)=D$2XXJTaeFHg@^6c}y$7+_ZKprRp}hM>5x^pH?4 zr`U=U&cj8xfvlu*_jOfz4{z_!8zi50x6 zC%!jOTZrKbkU2ETAPy#b!n@G!x?#!1p)a1 z$^xT#5yInhc^@MRqOIY3=mGV1-dZ)>qkYSTtt|q~t5mrGAbI(GucG7SG((e}F;|0V z>1J9-g?}SuV78A^siQ+=;w1j)DRoKcwTI*e2nImNWzqhhAZ7k#PWmsBNu_fKbq$xq0FDA`A38PXqVA=P|3xK_OikPibAJoHm!t3W#;#vr!c(&mW@HV`MgQG601)6ma{0L6MApfJ5MKl zPjIWh2I^wt6J;Y4k!lr&aGGlkr-v)kYMp^h%#&@so}RMkC@Ya#Mk*+Csil(&4MVB) zAz=CB`-5T4Qe&tXAb{u~VTb@4`uTr!6GB?S5KPl_haP$5CKFihe6G)1a!sjG>tT|A zCd%8SfCW3~p6)50l9d5Ns6k1DQPvRAaOHr2jCA@6Ovc$;DzOZVeSn9_!01>*a&KYF z+w~1&BHg|;%zA9Yh^dpY zqouvGo#StFTQN&(Q)YtSocVCE{diyKmvb&HBO5ybEfdp+e=Wm@!!0Kxv+nOVBVIP#ihllRV-~xo#ag2luhsmzre$JeqnC6xw6-)Bv^BT>}w_ENX((!BY^#9Zk0_J}d4h@}5f4?Cvtso;IPOWNd>1yieWN1zM zv2rIjOJ@sVI~yAX%a8bQbaMXnCkYtoWeor4@?T=)Hw1sAC^Gdm~e|1g`0nc;sY_Fn|}lh}WkwEq|C z&`W&SP%|_ANu0k+%KrtM-=*t6qWyQQ{{n^c!wmc1f%#vf<~L9*{~_iX{)q*{{~+;S zaQN%<{E5TA7>Nq(5keiPe|0+0ttne?b z`GvtB3dHi4P56Ia;qNv4A&~#n#(&MNKK`bit*L{Hq2q_X{PFpIRXik9+@h=YC7$hyVJY*!)ZM{Vl~G`uMjPf4um=Lx=gVo%%O)ev5??{Xfv* z_!oWtz2ko^@gKJ6AHn`#Rrb#W@*1uCGCtoggiSQdS)F7VRY4hu7XICbq+fR0AN+Et z50_GYOECVPwohFZ9?0`H?`{K%;>Z%G+_ZpFsXjAT@!7bUhn1y&{~Z zz%*w5^| z{Bzeo6#V}@TmO}4|B@RUnHU%v8JL);*gwEsUfD0ejgQhu(^AQeP2Wk=($h`S4BJmk zj>8UtlqfzC_B{$`?uF3AXpCN5>j&|ZSC5G7Ui&^A{KO-=; zPwck;L1JFA&Wt9VxS`qF)4|Zk*sM(F^a4(;^ZYy~Yt6cAv~39x2nIk@LZ{$A^5gFV z>Yph7Iv)RT{+$2>009C31O$Zpm4f{b1AhI4_7Mm05gi0?OA1&Y2IvtN2F>X~GKR)( z#yVmut+Fdpwh}{y7He5k)|f)3B9tx0z8j3^8t&Hn{{5fd{r^Aj^LgL*^P4`I@Avv% z%Q@#d=Uiu-nN5#oA~r+V+1S==X#dz&V7R$^0i6ZY2O6B<3bO~QkqGkvP9w|?N5nh0 z;_P6yez1dXt~SngFijblo~suy_mJUyCuTyb!QH9XU+V^2&i!K0Y3=a64$z?oSo~R-s0jC zmRFINH{@mX@%=4{f1KstNc<1g)3md1`n6TUA9=kREn`lb@6%tGqc%Ge$t$i26)qFy z@ww;xoEGK`nX56F;kVAQ66As*JU<3LHOg&VqmKe_8)!Fv;YjW1bh2V-^ zqiZhbKT+Y+j&M+_j@gYoSxfg3W4xQUijQ2y`$oaqo%czAIrBjMS_GY0UDvzmep~GG zT=@du)JQ)4wNuHrRbg>UPcPf@PlelhbnFd|&D-SR;}9(+G;uiDyq90bDqd8Ks5g5i z*hk$jb+a;XaPQjTC;yfiIfPlK!k=CZQV!UFD0$%3pn#H+gUkJKP6@P?|zN4GUA)AQda!guR$pP*XG}k!}n)B^~1RMzWuio<}+p}hjeEs^LN4BJ?i0^^qJI|oAarSwez=T?ycrNcVljK{)}XP zSjZaT#?l_?DfAmNB@#mhpv88;N3)) z0{5VCXT8?1rLtX3UyQI{*ikWlAVzyIziK3*G;7fjdjt3AhF$NXE44#(^pmFh)Xa_j zT(3hyK0mH$m|J~AGp=7?7w5K`Tb!3-wx+4T8U+uZIDbfw{eP>pS3g?!ic>S=RfZ;R zpHb<;-L{v4>CtD;M%oBht8bm21zNjgW^D0(2BYD{Y{Hys-OT>ATP0^*Eq6V8;?V!) zsPUflvAw;#e7)T=k|%b}EZ*UNd-n`(eV{3I$yJf!rhL0?mASe3%#vC>v5?z?`l+mf zc$$Ytb{}x8#O@Lu|CX@-Zm2+UxdQj+GoR&G0b3J=K!PLxmp}nvM?>vB`Zk`YaV|EV zc&v@{5xlgPo7b`*3xWmT90xcE3arSN{Lk|B-|!(&2xWzzF=z(e}i4F zd$ZWZhc>Ohx8_hi_;c9c^}6b2uR2-jRXPtAB5W3RG_ZK*;iylYY;=ZXtF$V;*X+J%7vZvZuwjO{Hor$YnR5uF!^nN7Ip zG2#<6V(VXeEkJo=mKV3AS+jmq?S%z+hl|ce_Mp6HkEq@E6uyoQ7FH3R7?El4+_*V?~!>RbmrTBH< zfA{|sS6s|L{Rd^l&(8Mp(m&bAfA3t$9%3=%PoB|o)%Z`te#Hk!5X+wafzQ8)wEa7{ z{BRwCQU1+J|8Y#hmScn8og)Q>U!eS9;2C(i5G~|jip%cj&xrgmP)uYG{)oyc{y3Zu zxOsud9!gdZZ%4FHT6Ps+%M^tzZyRiRN^lCZpo76z>igl#u)>zV(A^k@SPoQJE=QwJ2zXLw6Bf3wEgmVLxh3g zC3@!p_mb-X5p~a8sAAxzg zxj8%GJz)qLlnh)NF25IMPXGZ{A2)&%3@)Q2&YF{8XRl&>Q0vbb!5v!sw5O-Lima@U zkB^Lxyo?*cK^Bez0Vg?xECL}7dPo!fTs>`krCo`lV8LZb@W;Lnb0x|w10{oXbCJa# zlZDI3$$nqy8-L*4Tw$!0ZEW4VJkjD_UU)kdMFj<0gpI9&G!|tmC#`^0kdsE)!BNuo za1i-akjL5Ku&8hAx&H*`FAIVPU`2UA32>!ygy3f9g~buj;u=_jo2`u}>>!>9;-SvK z;82p0lYzq|%<-;vZazfGl>vGdW`b=!asy*ivY5gq)m`w46NfRZZat6}WwE@MvwsZv83!bvtQz0S^X!!nf)gvC1o{0)Ea0NwW)bIV2 z;YzGn#xMOqHjni)X}`6hlz)R6js$M}Z*&1|N}y=t*Re=><-d$YDaxUK!xxTHL@0om zw-2VmTdeyA3_cRK>SOa!teA0{QwvJrJoYwuk)eg ze%oIJkULi9{MU8m;h<*Y_cnRdUtpG3WJR8S8w+;iuWi566s(Js|H~Q*a&mvcLji&O zjrM?n6#q&C1thE7>{nP6;mE(hr>LOxmvt4De&1h&oFeM4d!!`K3L*Wv1`xu(z^8=z z>$=Kt`QLaKA*T!nS)f#4S>(GwJEtmrzBW8c8JYnP^>)&@>a_;SG;P~5Ek#z0M40J)Swg0HDS z$^e#AKq|`sY69gg10sFj<6?*Lu1>NVV8n6>iw1VtKR#-#Bf*L>5kZj2-OColi}3Et z9yWNFb$4?IH6I|B?~Id$%gf5kf*K@6IdB120x?9{g9N<2r?iU=$i8~Io%XW>0UkeB z8y8mSU)lxaX`Q9r?4@y_W`qEOXgFs(pw(r;df;m`_Jg<%jsQZ9;Gd=J5fBgr#DE#A ztFw+K7GBG{!m29yfguVd161;#C@RXsWq?Bce;tY#5N|l(2C5Equx_rJ-XK1K#^OD3 z{|IxyXTM+$M<~dE0Irgff($qZKt&taX^@SS`FFO~(Z<_mr36$(^`8Lot(@pP`QeI6 zGC%_U1Omw6|MMUK{rtCdP>_>Rg2NDSc^RM{loU}itUT1Wbm{+=$wBOqNOZ9wILRzu z0YhRXpoF(^c5{%$*ty}+a1e}?Q<4XPB?Md<394gv+kvuI5IhE(yW0*JM^->EUEI;% zLw!pBh_pag{ViSyxD2ox5P-8m5MK!a!o>dsF97&Tc=&hV{}F6JPyGs;yn+l+R6yuu zz`3e`LM-3G5i)S)e?as9Qn4UVvdXe@%0RIw$s&NohJeFC_@5OU_axx4ASmY!bOQKn z03JtV=@SBu2#P#hJ*Ay({BVSSgd8wP{th_>AWJ}(D9RyacBCKm}7!l$U}3JKE#lIv5aeStVIHrDYTmaD<|=GN?JUSveJ0`?q{Z;J)GPDh=|( z(#~!^(ysqt?^t%!H@ucpL$Kx4lkv(?b^v65Si)<18u&DJpe&uW(ZPLV4Wsc?kV8Z2>HTcV#=iB=l2qXdu;Q%eb z+LdFAT)76dQxHhJ6Kd%c|Q-ashXP(u6CbE7>5Pi$7 zKz?|s|0qlMJ<$Cxb8sM)$4VUi50Yx?oSd-bIsQeaNgRYkR`PBdoPE+A3-w zZ2s&S@EyKoNS1N_j*X_Tr;eSvEeei8;&ArT%C@#xX$3f3LE2W{1|^M!E7&1%wm5r5 z`yW`Y4Ec2$En6^)B0>=Xj06zIP(~>t<-RYw{P5TQrfy!?(=0lxBffY0(YCTJ%ZV0e z{K}3k-~72{-$$(M=U)?+|27}}Tlp>)06)@NEZDxMwpIXTG0wlpZ>gISyojv2FT5)Z zFci*)fIST=DhV)_;R>p9VSb>A2$O~#IqgTpV~H>~d)N_Y8(=lTBv`u7S3yC}-B)r2 z#b0Q_%9ybL`;jyQ!m~`JpQPvCmndLw{UT1RocyvNfd@d4KxTP)HE^f05;#&nga@Vq zOdptcI8X4&LN!+Y@7uHg5hx(p|M#GL(_t&1fNnqMh}93+xOxMs8M90n0x(x#K-SPd z$rp?zQ|O=M2(~Oc=%3^TT>l~0 zKcc`t>ii$>`VYDO5e5EH=l^imf5`QZDDaOu|Nn@)ez>&2_FGB3F111quw458(Tg?7 z|7Zf%;H5IirnPJZYfiJX?S!n_#KyjfZRsUM1jGPVugtyTw}bmt>>R7tK-aG0Tn{?r zZUmnkVP{{(!M=Jm2M7+Z1+XFl9Gg~e-T~KGv&F~;y3>OfaW3-CTG9QF%lVAoj*7|K z63(yV-1-NxAVKX&{C78Kt(oW?s6J-xhr zeEmp47cO49eC29zRP^;5F|jw}Zrx3}mzqXN&$$2OX-;llenH{07ZopGRaRBk)HXIX zziXkr|M2nim#*%f-oCH>17qV8lT*_(vvUjC<`yP zRX!}lH*u`q0bjFO!w72Qv1KRX+*;oKk#`=KuM?Fw9_6zoyye^~rto>!7z?#!%>F&Z z&i}VC`;OQTygov>*xA75v2TK4APc*x*+PD3m9Fdz`ed3)AAe^wwF!z2&$pT4+r>B5 zw+Jc7EuDI@XtcE}WC`-eevfkD#JK)BlYI>&cX?*OT*h&N95=jGB(^a{Ms1!~de z_2h__!{Zpi=p_g(J)9$4_p#9vVR+5R)YO7w${vhNX|KJuCa+mWd%eq|A35TdA#+Xa zc)*KbiL|Xb&hy6?%MTHtgupmVEN{*chdp@Ly5W8@W_FdZhH!G@rjGPscyy(<5J~ux z%6wBHRWz(B->qsgIgu2IWbeo~tm^OAxSm3`qI)Fya*YQ(bI2pBdoWDj)QN4@R*-qC z$9t|TQl~8}^tyEg2cI>+h*41dgb4c^?h>#b{T4wMDXu1hjqekkP&=w+HaQSd{I%wI zu2_>k+C*Q`J~6yrHIte?c&qA*OlaCbO-8?p+ZE?7iw!o4s_zFIyI%zFcy^p$Y1&Re zoFl$3y^GRl)1)qZqJ1{jxWyA~Vw{`j>uHJ6E4G+++23<~i0>t`++_fC4R^PRYu-G%2n>RNj@ou6NG*rVo>b>NXW(X&#f zez?HfGFii|{gmuUX2m%~k<5B{9WlNSap{juw~b!bUfPAAa;A@wlI6ne)!dwVhXyogrM^U5eFb z&OAFm@lxefg44FVJ2t5=6t6w-JkFObcGPA)X>MK3-az9X!-j{3l-ZFl_76U9aGlXR zFUu|cGW{t&3jOrgXy{Em`3=JwKSkKd~)9lz;5wAWQs!0gz79{hpHx^0F~ zLB8Vz<9iACS}%I@nTEU9`P9@-I=^#pL*A-0x$3hwGhd*5rwnRfRd)M;UsXmuR$uzH z*c=tsuvXjy%@BSW<;zb!(-nS1*q-91u%)v)eO!BY8~mu*-gOXbE-&#WLC-E9>nDe{ z9_7g3x^qr2EVH`GnS9YcP(G|o$}#>c?ZMzcr2!)0WA8OxMsm6=TU?BcytV}wrPc`$UJ;dX#H6xm3m2EITJ@ilJR zRowgs{H0;t=0{f>cp(o8LR?{e#YFSiQ>N;sQXJ79IUadCB8XwPUvzynumN-D`Rq@OHYHj1hb7N10=pVBDEX$`#mYkc_>8xiv zqe|`y-*!y<;qDBt=?%Nfn;(5xzeW0mM3k6nyn;v6d(BJ68n$UA`%PlmN8rdxf{q$D zCCiCUy%?xGx)^@Bd(=GC^%PA%_w-0k-RKk7OMW^|w=KuSvQ||$)ZC=ji6tkR^BE~` zm;S@T&93EBX?ASmtVd|w*cokVg4$+^-s-EzEnf4XaHd4bidgQk+T4Dml*lpDKC4@s zUaA;)=bXqLGbvBpR4{sU2@;|vlB%6jf2XA0_|=i@+b*OU&cmkicYIU5yu2cU_#=l+ppo*V9Z zcJ6F4m&e()cW*`M>wH2-x3~Myx=APfwD%@$e*4mHgnip}!ose-IOn7fRWg1_@)^c? zYkUJwoUG#-m3yEfd4Rq#yAIzzedc)A5`^FC^mzZX*ekhu>9S+JAB!vITsRE)U61Uu zZcL|-Z@iojeO1$1rSTQQE>OmPmgGP|^`V{awq%vieAKRx2|+byw=xqh}-+A!yNhr-7)qQe3 zMZolWA8(RWulJ`XJKIJL)QgzpuB3kBOVH9&RRZb952?53To)FxqBE?dYjh(H$Z`

    Xu`4)Vi9gH2CaBG;tvvCm7);*hdpmzb??gsWU>h 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 QNN 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

    +yBm&skM6=EH7e{2E(Cf31D_e4P4_uSr0R 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ļ=KDCq_eWQ781ocid)b9Rq$9_3`n|ATFy$YS2#s% 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 LdiCnVr}pSSZ4Wdm literal 0 HcmV?d00001 diff --git a/examples/DIIID-like_SLAYER_example/slayer_ex.ipynb b/examples/DIIID-like_SLAYER_example/slayer_ex.ipynb new file mode 100644 index 000000000..0fb8f9079 --- /dev/null +++ b/examples/DIIID-like_SLAYER_example/slayer_ex.ipynb @@ -0,0 +1,72 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "0", + "metadata": {}, + "outputs": [], + "source": [ + "using Pkg\n", + "Pkg.activate(\"/Users/bursche/Documents/GitHub/JPEC_BCRIT\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1", + "metadata": {}, + "outputs": [], + "source": [ + "Base.active_project()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2", + "metadata": {}, + "outputs": [], + "source": [ + "using GeneralizedPerturbedEquilibrium\n", + "using Plots\n", + "using GeneralizedPerturbedEquilibrium: Analysis" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3", + "metadata": {}, + "outputs": [], + "source": [ + "h5path = \"/Users/bursche/Documents/GitHub/JPEC_BCRIT/examples/DIIID-like_SLAYER_example/gpec.h5\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4", + "metadata": {}, + "outputs": [], + "source": [ + "p_eq = Analysis.Equilibrium.plot_equilibrium_summary(h5path)\n", + "p_ffs = Analysis.ForceFreeStates.plot_ffs_summary(h5path)\n", + "#p_pe = Analysis.PerturbedEquilibrium.plot_perturbed_equilibrium_summary(h5path)\n", + "\n", + "display(p_eq)\n", + "display(p_ffs)\n", + "#display(p_pe)" + ] + } + ], + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/src/GeneralizedPerturbedEquilibrium.jl b/src/GeneralizedPerturbedEquilibrium.jl index 96f9f4b1a..5d388d8bf 100755 --- a/src/GeneralizedPerturbedEquilibrium.jl +++ b/src/GeneralizedPerturbedEquilibrium.jl @@ -47,6 +47,7 @@ export Tearing # Backward-compat top-level aliases so callers can still reach these # directly; the canonical nested path is `Tearing.{Dispersion,Runner}`. import .Tearing.Dispersion as Dispersion +import .Tearing.CriticalResonantField as CriticalResonantField import .Tearing.Runner as Runner export Dispersion, Runner diff --git a/src/Tearing/CriticalResonantField/CriticalResonantField.jl b/src/Tearing/CriticalResonantField/CriticalResonantField.jl new file mode 100644 index 000000000..453f04b73 --- /dev/null +++ b/src/Tearing/CriticalResonantField/CriticalResonantField.jl @@ -0,0 +1,21 @@ +# CriticalResonantField.jl +# +# Uses the inner-layer delta from InnerLayer.jl to find the critical resonant field +# required for mode penetration at each rational surface. This can then be compared +# to the actual resonant field from the perturbed equilibrium to determine which modes +# are predicted to penetrate. + +module CriticalResonantField + +using LinearAlgebra +using StaticArrays + +using ..InnerLayer +using ..InnerLayer: InnerLayerModel, solve_inner, GGJModel, GGJParameters, + SLAYERModel, SLAYERParameters + +#include("TorqueBalance.jl") + +#export TorqueBalance, torque_balance + +end # module CriticalResonantField diff --git a/src/Tearing/CriticalResonantField/TorqueBalance.jl b/src/Tearing/CriticalResonantField/TorqueBalance.jl new file mode 100644 index 000000000..c85bff102 --- /dev/null +++ b/src/Tearing/CriticalResonantField/TorqueBalance.jl @@ -0,0 +1,122 @@ +# TorqueBalance.jl +# +# `TorqueBalance` solves the torque balance eqution for each rational surface. +# It follows the derivation found in Cole PopP 2006. For simplicity, the script +# uses equation 62 of Cole. This can be improved by incorporating the true +# outer-layer Δ' from the perturbed equilibrium and then solving equation 61. +# +# The viscous torque is: +# +# T_v = 2 · P (Q_0 - Q) / ((S kappa^hat) · (b_r(r_s)/B_phi))^2 +# +# The electromagnetic torque is: +# +# T_em = Im[Δ_inner(Q)] / |alpha + Δ_inner(Q)|^2 +# +# Now solving for critical resonant field, we have: +# +# (b_r(r_s)/B_phi))^2_crit = max(2 · P (Q_0 - Q) / ((S kappa^hat) · Im[-Δ_inner(Q)^-1]) +# +# Normalizations, definitions, and other conventions are taken from the Cole paper. +# The critical resonant field is found at each rational surface. For each, the script +# scans over a range of Q values and finds the maximum value of the right-hand side of +# the equation above. + +""" + TorqueBalance{M<:InnerLayerModel, P} + +Per-surface dispersion data: `(model, params, dp_diag, dc, scale, tauk)`. +Calling `sc(Q)` returns the complex residual + +``` +r(Q) = dp_diag - scale * solve_inner(model, params, Q).tearing - dc +``` + +A root of `sc` in the complex `Q` plane is a **tearing** eigenvalue at +this surface in the *uncoupled* approximation (only the tearing channel +of the inner-layer response appears — the interchange channel enters the +full 2m×2m dispersion via `MultiSurfaceCoupling`, not this scalar form). +Coupled multi-surface eigenvalues come from `MultiSurfaceCoupling` +evaluating the determinant of the modified Δ' matrix. +""" +struct SurfaceCoupling{M<:InnerLayerModel,P} + model::M + params::P + dp_diag::ComplexF64 + dc::Float64 + scale::Float64 + tauk::Float64 +end + +function (sc::SurfaceCoupling)(Q::Number) + Δ = solve_inner(sc.model, sc.params, ComplexF64(Q)).tearing + return sc.dp_diag - sc.scale * Δ - sc.dc +end + +""" + surface_coupling(model::SLAYERModel, params::SLAYERParameters, + dp_diag::Number; dc::Real=0.0) -> SurfaceCoupling + +SLAYER convenience constructor. `scale` is set to `params.lu^(1/3)` so that +the dimensionless Δ from `riccati_f` is mapped to outer ψ-units before +subtraction from the Δ' diagonal. `tauk` is taken from `params.tauk` for use +by `MultiSurfaceCoupling` Q rescaling. +""" +function surface_coupling(model::SLAYERModel, params::SLAYERParameters, + dp_diag::Number; dc::Real=0.0) + return SurfaceCoupling(model, params, ComplexF64(dp_diag), + Float64(dc), params.lu^(1 / 3), params.tauk) +end + +""" + surface_coupling(model::GGJModel, params::GGJParameters, + dp_diag::Number) -> SurfaceCoupling + +GGJ convenience constructor. `scale` is `1.0` because GGJ's `solve_inner` +applies its own `rescale_delta` (S^(2p₁/3)·v1^(2p₁)) internally, so the +returned Δ is already in outer units. `tauk` defaults to `1.0` (GGJ has no +direct analogue of SLAYER's per-surface time normalization, so multi-surface +Q rescaling is a no-op for GGJ surfaces unless overridden). + +**No `dc` kwarg**: GGJ's 4m×4m Pletzer-Dewar residual already includes the +interchange channel, which provides Glasser (Mercier) stabilization +natively. A Δ_crit proxy (χ_parallel-matching offset on the diagonal) is +meaningful only for tearing-only slab-layer approximations like SLAYER; +for GGJ it would double-count the interchange physics. The `SurfaceCoupling` +struct's `dc` field is hard-wired to 0 here. +""" +function surface_coupling(model::GGJModel, params::GGJParameters, + dp_diag::Number) + return SurfaceCoupling(model, params, ComplexF64(dp_diag), + 0.0, 1.0, 1.0) +end + +""" + surface_coupling(model::InnerLayerModel, params, dp_diag::Number; + dc::Real=0.0, scale::Real=1.0, tauk::Real=1.0) + -> SurfaceCoupling + +Generic fallback constructor. Use this when wiring a new inner-layer model +into the dispersion solver — pass the appropriate inner→outer-units `scale` +and per-surface `tauk` explicitly. +""" +function surface_coupling(model::InnerLayerModel, params, dp_diag::Number; + dc::Real=0.0, scale::Real=1.0, tauk::Real=1.0) + return SurfaceCoupling(model, params, ComplexF64(dp_diag), + Float64(dc), Float64(scale), Float64(tauk)) +end + +function torque_balance_value(tb::TorqueBalance, Q::Number) + Δ = solve_inner(tb.model, tb.params, ComplexF64(Q)).tearing + jxb = -imag(1.0 / (Δ + tb.delta_n_p)) + return 2.0 * tb.P * (tb.Q0 - Q) / jxb +end + +function scan_torque_balance(tb; Qmin=-10.0, Qmax=10.0, nscan=200) + qs = range(Qmin, Qmax; length=nscan) + vals = torque_balance_value.(Ref(tb), qs) + idx = argmax(vals) + return qs[idx], vals[idx] +end + +br_th = sqrt(maxbal / tb.lu * (tb.sval^2 / 2.0)) diff --git a/src/Tearing/CriticalResonantField/bcrit_dev.ipynb b/src/Tearing/CriticalResonantField/bcrit_dev.ipynb new file mode 100644 index 000000000..a6186408f --- /dev/null +++ b/src/Tearing/CriticalResonantField/bcrit_dev.ipynb @@ -0,0 +1,285 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "0", + "metadata": {}, + "outputs": [], + "source": [ + "using Pkg\n", + "Pkg.activate(\"/Users/bursche/Documents/GitHub/JPEC_BCRIT\")\n", + "Base.active_project()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1", + "metadata": {}, + "outputs": [], + "source": [ + "using GeneralizedPerturbedEquilibrium\n", + "using GeneralizedPerturbedEquilibrium: Analysis\n", + "using GeneralizedPerturbedEquilibrium: InnerLayer\n", + "using GeneralizedPerturbedEquilibrium.InnerLayer: solve_inner\n", + "using GeneralizedPerturbedEquilibrium: Tearing\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2", + "metadata": {}, + "outputs": [], + "source": [ + "using Plots\n", + "default(\n", + " fontfamily=\"Georgia\",\n", + " margin=12Plots.mm,\n", + " size=(800, 500),\n", + " dpi=150\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3", + "metadata": {}, + "outputs": [], + "source": [ + "struct TorqueBalance\n", + " model\n", + " params\n", + " Q0::Float64\n", + " P::Float64\n", + " delta_n_p::Float64\n", + " lu::Float64\n", + " sval::Float64\n", + "end\n", + "\n", + "function torque_balance_value(tb::TorqueBalance, Q::Number)\n", + " Δ = solve_inner(tb.model, tb.params, ComplexF64(Q)).tearing\n", + " jxb = -imag(1.0 / (Δ + tb.delta_n_p))\n", + " return 2.0 * tb.P * (tb.Q0 - Q) / jxb, Δ\n", + "end\n", + "\n", + "function torque_balance_scan(tb; Qmin=-10.0, Qmax=10.0, n=200)\n", + " Qs = range(Qmin, Qmax; length=n)\n", + " torque_out = [torque_balance_value(tb, q) for q in Qs]\n", + " bal = [x[1] for x in torque_out]\n", + " Δs = [x[2] for x in torque_out]\n", + " #bal = [torque_balance_value(tb, q) for q in Qs]\n", + " positive = isfinite.(bal) .& (bal .> 0.0)\n", + "\n", + " if !any(positive)\n", + " return Qs, bal, NaN, 0.0\n", + " end\n", + " i = argmax(bal)\n", + " Qpeak_ind = i\n", + " Qs_positive = Qs[positive]\n", + " bal_positive = bal[positive]\n", + "\n", + " i = argmax(bal_positive)\n", + " Qpeak = Qs_positive[i]\n", + " \n", + " maxbal = bal_positive[i]\n", + "\n", + " br_crit = sqrt(maxbal / tb.lu * (tb.sval^2 / 2.0))\n", + " return Qs, bal, Qs_positive, bal_positive, Qpeak, br_crit, Qpeak_ind, Δs\n", + "end" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4", + "metadata": {}, + "outputs": [], + "source": [ + "# You can substitute any valid SLAYERParameters you already have.\n", + "# This is just an example skeleton.\n", + "p = GeneralizedPerturbedEquilibrium.InnerLayer.slayer_parameters(\n", + " n_e=1e19, t_e=1e3, t_i=1e3,\n", + " omega=0.0, omega_e=4, omega_i=-2,\n", + " qval=2.0, sval_r=0.5, bt=2.0, rs=1.0, R0=3.0, mu_i=2.0, zeff=1.0,\n", + " chi_perp=1.0, chi_tor=1.0, m=2, n=1\n", + ")\n", + "p2 = GeneralizedPerturbedEquilibrium.InnerLayer.SLAYERParameters(\n", + " ising=p.ising,\n", + " m=p.m, n=p.n,\n", + " tau=p.tau, lu=p.lu, c_beta=p.c_beta, D_norm=p.D_norm,\n", + " P_perp=p.P_perp, P_tor=p.P_tor,\n", + " Q_e=4 / p.tauk, Q_i=-10 / p.tauk, iota_e=p.iota_e,\n", + " tauk=p.tauk, tau_r=p.tau_r, delta_n=p.delta_n,\n", + " rs=p.rs, R0=p.R0, bt=p.bt, sval_r=p.sval_r,\n", + " dr_val=p.dr_val, dgeo_val=p.dgeo_val,\n", + " eta=p.eta, d_beta=p.d_beta,\n", + " dc_tmp=p.dc_tmp, dc_type=p.dc_type\n", + ")\n", + "\n", + "#p = p2\n", + "\n", + "tb = TorqueBalance(\n", + " GeneralizedPerturbedEquilibrium.InnerLayer.SLAYERModel(;),\n", + " p,\n", + " 0.5,\n", + " 1.0,\n", + " 1e-2,\n", + " p.lu,\n", + " p.sval_r\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"\n", + "\n", + "tau_h=R0*(mu0*rho)**0.5/(nns*sval*bt) ! alfven time across surface\n", + "lu=tau_r/tau_h ! Lundquist number\n", + "Qconv=lu**(1.0/3.0)*tau_h ! conversion to Qs based on Cole\n", + "\n", + "! note Q depends on Qconv even if omega is fixed.\n", + "Q=Qconv*omega\n", + "Q_e=-Qconv*omega_e\n", + "Q_i=-Qconv*omega_i\n", + "\n", + "\"\"\"\n", + "2=-lu**(1.0/3.0)*tau_h *OE\n", + "2 = tauk *OE" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6", + "metadata": {}, + "outputs": [], + "source": [ + "Qs = range(-5.0, 5.0, length=200)\n", + "\n", + "vals = [torque_balance_value(tb, q) for q in Qs]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"\n", + "n=2000:\n", + "Qpeak = 0.24512256128064033\n", + "maxbal = 0.35873684252530247\n", + "br_crit = 4.668551985584323e-5\n", + "\n", + "n=200 (def):\n", + "Qpeak = 0.25125628140703515\n", + "maxbal = 0.3585219071071706\n", + "br_crit = 4.667153206033017e-5\n", + "\"\"\"\n", + "Qs, bal, Qs_positive, bal_positive, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb)\n", + "\n", + "println(\"Qpeak = \", Qpeak)\n", + "println(\"maxbal = \", maximum(bal_positive))\n", + "println(\"maxbal = \", maximum(bal))\n", + "println(\"br_crit = \", brcrit)\n", + "\n", + "p1 = plot(Qs, bal, lw=2, label=\"balance\")\n", + "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", + "xlabel!(\"Q\")\n", + "ylabel!(\"balance\")\n", + "title!(\"Torque-balance scan\")\n", + "\n", + "p2 = plot(Qs_positive, bal_positive, lw=2, label=\"balance (positive)\")\n", + "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", + "xlabel!(\"Q\")\n", + "ylabel!(\"balance\")\n", + "title!(\"Torque-balance scan\")\n", + "\n", + "plot(p1, p2, layout=(2,1), size=(800, 1000))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8", + "metadata": {}, + "outputs": [], + "source": [ + "Qpk = Qs_positive[argmax(bal_positive)]\n", + "j = findfirst(isequal(Qpk), Qs)\n", + "\n", + "lhs = 2*tb.P*(tb.Q0 - Qpk) / jxbs[j]\n", + "br_ratio = sqrt(lhs / (tb.lu * tb.sval^2 / 2))\n", + "\n", + "rhs = (tb.lu * tb.sval^2 / 2) * br_ratio^2\n", + "\n", + "println(\"lhs = \", lhs)\n", + "println(\"rhs = \", rhs)\n", + "println(\"lhs/rhs = \", lhs / rhs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9", + "metadata": {}, + "outputs": [], + "source": [ + "#Δs = [solve_inner(tb.model, tb.params, ComplexF64(q)).tearing for q in Qs]\n", + "jxbs = [-imag(1.0 / (d + tb.delta_n_p)) for d in Δs]\n", + "T_VISC = [2.0 * tb.P * (tb.Q0 - q) for (q, jxb) in zip(Qs, jxbs)]\n", + "br_t = brcrit\n", + "println(tb.lu, \" \", tb.sval, \" \", br_t, \" \", p.bt, \" \", tb.delta_n_p)\n", + "T_EM = tb.lu * tb.sval^2/2 * (br_t / p.bt)^2 * jxbs\n", + "i = Qpeak_ind\n", + "println(T_VISC[i]/(tb.lu * tb.sval^2/2 * (brcrit)^2 * jxbs[i]))\n", + "println(T_VISC[i] / (tb.lu * tb.sval^2/2 * (brcrit * p.bt)^2 * jxbs[i]))\n", + "println(T_VISC[i] / ( (brcrit / p.bt)^2 * jxbs[i]))\n", + "\n", + "#T_EM ∝ S ξ̂ (br/Bφ)² Im[-Δ̂(Q)⁻¹]\n", + "#T_visc ∝ 2 P (Q0 − Q)\n", + "\n", + "p1 = plot(Qs, imag.(Δs), label=\"Im(Δ)\", lw=2)\n", + "#plot!(p1, Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", + "xlabel!(p1, \"Q\")\n", + "ylabel!(p1, \"Δ\")\n", + "title!(p1, \"Inner-layer Δ(Q)\")\n", + "\n", + "p2 = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", + "plot!(p2, Qs, T_VISC, label=\"2P(Q0-Q)\", lw=2)\n", + "plot!(p2, Qs, T_EM, label=\"T_EM\", lw=2)\n", + "xlabel!(p2, \"Q\")\n", + "ylabel!(p2, \"jxb\")\n", + "title!(p2, \"jxb(Q) = -Im[1/(Δ + δ_n_p)]\")\n", + "\n", + "p3 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2)\n", + "plot!(p3, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", + "xlabel!(p3, \"Q\")\n", + "ylabel!(p3, \"balance\")\n", + "title!(p3, \"2P(Q0-Q)/jxb\")\n", + "\n", + "plot(p1, p2, p3, layout=(3,1), size=(800, 1000))" + ] + } + ], + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/src/Tearing/CriticalResonantField/bcrit_dev_ggj.ipynb b/src/Tearing/CriticalResonantField/bcrit_dev_ggj.ipynb new file mode 100644 index 000000000..94f04beac --- /dev/null +++ b/src/Tearing/CriticalResonantField/bcrit_dev_ggj.ipynb @@ -0,0 +1,208 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "0", + "metadata": {}, + "outputs": [], + "source": [ + "using Pkg\n", + "Pkg.activate(\"/Users/bursche/Documents/GitHub/JPEC_BCRIT\")\n", + "Base.active_project()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1", + "metadata": {}, + "outputs": [], + "source": [ + "using GeneralizedPerturbedEquilibrium\n", + "using GeneralizedPerturbedEquilibrium: GGJParameters\n", + "using GeneralizedPerturbedEquilibrium\n", + "using GeneralizedPerturbedEquilibrium: InnerLayer\n", + "using GeneralizedPerturbedEquilibrium.InnerLayer: solve_inner\n", + "import GeneralizedPerturbedEquilibrium.InnerLayer.GGJ: sfac\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2", + "metadata": {}, + "outputs": [], + "source": [ + "using Plots\n", + "default(\n", + " fontfamily=\"Georgia\",\n", + " margin=12Plots.mm,\n", + " size=(800, 500),\n", + " dpi=150\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3", + "metadata": {}, + "outputs": [], + "source": [ + "struct TorqueBalance\n", + " model\n", + " params\n", + " Q0::Float64\n", + " P::Float64\n", + " delta_n_p::Float64\n", + " lu::Float64\n", + " sval::Float64\n", + "end\n", + "\n", + "function torque_balance_value(tb::TorqueBalance, Q::Number)\n", + " Δ = solve_inner(tb.model, tb.params, ComplexF64(Q)).tearing\n", + " jxb = -imag(1.0 / (Δ + tb.delta_n_p))\n", + " return 2.0 * tb.P * (tb.Q0 - Q) / jxb\n", + "end" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4", + "metadata": {}, + "outputs": [], + "source": [ + "# You can substitute any valid SLAYERParameters you already have.\n", + "# This is just an example skeleton.\n", + "p = GeneralizedPerturbedEquilibrium.InnerLayer.slayer_parameters(\n", + " n_e=1e19, t_e=1e3, t_i=1e3,\n", + " omega=0.0, omega_e=4, omega_i=-2,\n", + " qval=2.0, sval_r=0.5, bt=2.0, rs=1.0, R0=3.0, mu_i=2.0, zeff=1.0,\n", + " chi_perp=1.0, chi_tor=1.0, m=2, n=1\n", + ")\n", + "\n", + "tb = TorqueBalance(\n", + " GeneralizedPerturbedEquilibrium.InnerLayer.SLAYERModel(;),\n", + " p,\n", + " 0.5,\n", + " 1.0,\n", + " 1e-2,\n", + " p.lu,\n", + " p.sval_r\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5", + "metadata": {}, + "outputs": [], + "source": [ + "p_ggj = GeneralizedPerturbedEquilibrium.InnerLayer.glasser_wang_2020_eq55()\n", + "lu_ggj = sfac(p_ggj)\n", + "sval_ggj = 0.5\n", + "\n", + "tb = TorqueBalance(\n", + " GeneralizedPerturbedEquilibrium.InnerLayer.GGJModel(; solver=:ray),\n", + " p_ggj,\n", + " 0.5,\n", + " 1.0,\n", + " 1e-2,\n", + " lu_ggj,\n", + " sval_ggj\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"\n", + "\n", + "tau_h=R0*(mu0*rho)**0.5/(nns*sval*bt) ! alfven time across surface\n", + "lu=tau_r/tau_h ! Lundquist number\n", + "Qconv=lu**(1.0/3.0)*tau_h ! conversion to Qs based on Cole\n", + "\n", + "! note Q depends on Qconv even if omega is fixed.\n", + "Q=Qconv*omega\n", + "Q_e=-Qconv*omega_e\n", + "Q_i=-Qconv*omega_i\n", + "\n", + "\"\"\"\n", + "2=-lu**(1.0/3.0)*tau_h *OE\n", + "OE = -2 " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7", + "metadata": {}, + "outputs": [], + "source": [ + "Qs = range(-5.0, 5.0, length=200)\n", + "\n", + "vals = [torque_balance_value(tb, q) for q in Qs]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8", + "metadata": {}, + "outputs": [], + "source": [ + "plot(Qs, real.(vals), label=\"Re(balance)\", lw=2)\n", + "plot!(Qs, imag.(vals), label=\"Im(balance)\", lw=2)\n", + "xlabel!(\"Q\")\n", + "ylabel!(\"torque balance\")\n", + "title!(\"tb(Q)\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9", + "metadata": {}, + "outputs": [], + "source": [ + "Δs = [solve_inner(tb.model, tb.params, ComplexF64(q)).tearing for q in Qs]\n", + "jxbs = [-imag(1.0 / (d + tb.delta_n_p)) for d in Δs]\n", + "\n", + "p1 = plot(Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", + "plot!(p1, Qs, imag.(Δs), label=\"Im(Δ)\", lw=2)\n", + "xlabel!(p1, \"Q\")\n", + "ylabel!(p1, \"Δ\")\n", + "title!(p1, \"Inner-layer Δ(Q)\")\n", + "\n", + "p2 = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", + "xlabel!(p2, \"Q\")\n", + "ylabel!(p2, \"jxb\")\n", + "title!(p2, \"jxb(Q) = -Im[1/(Δ + δ_n_p)]\")\n", + "\n", + "p3 = plot(Qs, real.(vals), label=\"Re(balance)\", lw=2)\n", + "plot!(p3, Qs, imag.(vals), label=\"Im(balance)\", lw=2)\n", + "xlabel!(p3, \"Q\")\n", + "ylabel!(p3, \"balance\")\n", + "title!(p3, \"2P(Q0-Q)/jxb\")\n", + "\n", + "plot(p1, p2, p3, layout=(3,1), size=(800, 1000))" + ] + } + ], + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/src/Tearing/CriticalResonantField/gslayer.txt b/src/Tearing/CriticalResonantField/gslayer.txt new file mode 100644 index 000000000..91cc2f862 --- /dev/null +++ b/src/Tearing/CriticalResonantField/gslayer.txt @@ -0,0 +1,466 @@ + MODULE gslayer_mod + + USE sglobal_mod, ONLY: out_unit, r8, mu0, m_p, chag, lnLamb, + $ Q_e,Q_i,pr,pe,c_beta,ds,tau, + $ eta,visc,rho_s,lu,omega_e,omega_i, + $ delta_n,layfac, + $ Q + USE delta_mod, ONLY: riccati,riccati_out, + $ parflow_flag,PeOhmOnly_flag + + IMPLICIT NONE + +c----------------------------------------------------------------------- +c torque balance scan resolution. public so that gpout_singfld can +c size the netcdf dimension from the same source of truth. +c----------------------------------------------------------------------- + INTEGER, PARAMETER :: slayer_inum=200 + INTEGER, PARAMETER :: slayer_nref=4 +c----------------------------------------------------------------------- +c dedicated logarithmic sampling window bracketing Q_e, the electron +c diamagnetic frequency. (Q-Q_e) sits in the denominator of both G +c and C3 in delta.f, so the layer solve is singular there; the +c coarse scan steps over that neighbourhood with dQ=0.1 and the +c adaptive refinement only visits it when the torque-balance peak +c happens to land on it. These samples always resolve it, so the +c structure can be inspected on every surface rather than only on +c the ones that fell into it. +c +c PURELY DIAGNOSTIC: filled after br_th is computed, and tagged +c kpass=slayer_qetag so the threshold search cannot see them. +c Costs slayer_nqe extra lsode solves per surface (~40% on top of +c the 1005 the scan already does). +c----------------------------------------------------------------------- + INTEGER, PARAMETER :: slayer_nqe=400 + INTEGER, PARAMETER :: slayer_qetag=99 + REAL(r8), PARAMETER :: slayer_qefar=1.0e-1_r8 + REAL(r8), PARAMETER :: slayer_qenear=1.0e-9_r8 + INTEGER, PARAMETER :: slayer_nq=(slayer_inum+1)*(slayer_nref+1) + $ +slayer_nqe +c----------------------------------------------------------------------- +c every term of Cole & Fitzpatrick Eq. (61) on one rational +c surface, +c Im[Delta]/|alpha+Delta|**2 +c = 2*P*(Q0-Q)/(S*kappa_hat*(b_r/B_phi)**2) +c recorded so the balance can be rebuilt piece by piece and +c rescanned in post processing. every component is default +c initialized, so both ALLOCATE and INTENT(OUT) leave a well +c defined (zero) state even when the layer solve is skipped. +c +c kpass tags the scan pass that produced each sample: 0 for the +c coarse scan, 1..slayer_nref for the adaptive refinement passes. +c----------------------------------------------------------------------- + TYPE :: slayer_diag_type + REAL(r8), DIMENSION(slayer_nq) :: qs=0.0_r8 + REAL(r8), DIMENSION(slayer_nq) :: lhs=0.0_r8 + REAL(r8), DIMENSION(slayer_nq) :: rhs=0.0_r8 + REAL(r8), DIMENSION(slayer_nq) :: bal=0.0_r8 + REAL(r8), DIMENSION(slayer_nq) :: brb=0.0_r8 + COMPLEX(r8), DIMENSION(slayer_nq) :: dlt=(0.0_r8,0.0_r8) + INTEGER, DIMENSION(slayer_nq) :: kpass=0 + REAL(r8) :: alpha=0.0_r8, kaphat=0.0_r8, slun=0.0_r8 + REAL(r8) :: prnd=0.0_r8, q0v=0.0_r8, qcnv=0.0_r8 + REAL(r8) :: qev=0.0_r8, qiv=0.0_r8, dsv=0.0_r8 + REAL(r8) :: cbeta=0.0_r8, tratio=0.0_r8, pev=0.0_r8 + REAL(r8) :: lfac=0.0_r8, dnorm=0.0_r8, rhos=0.0_r8 + REAL(r8) :: etav=0.0_r8, viscv=0.0_r8, tauh=0.0_r8 + REAL(r8) :: taur=0.0_r8, tauv=0.0_r8, taui=0.0_r8 + REAL(r8) :: shr=0.0_r8, bl=0.0_r8, va=0.0_r8 + REAL(r8) :: rhom=0.0_r8, lbet=0.0_r8, omg=0.0_r8 + REAL(r8) :: qsol=0.0_r8, wsol=0.0_r8, brth=0.0_r8 + REAL(r8) :: mxbal=0.0_r8, qmn=0.0_r8, qmx=0.0_r8 + END TYPE slayer_diag_type + + CONTAINS + +c----------------------------------------------------------------------- +c subprogram 1. gpec_slayer. +c run slayer to provide b_crit(ising). +c----------------------------------------------------------------------- +c----------------------------------------------------------------------- +c declarations. +c----------------------------------------------------------------------- + SUBROUTINE gpec_slayer(n_e,t_e,n_i,t_i,zeff,omega,omega_e, + $ omega_i,qval,sval,bt,rs,R0,mu_i,inpr,mms,nns,ascii_flag, + $ delta,psi0,jxb,omega_sol,br_th,diag,inlayfac,inlayfrac) + + REAL(r8),INTENT(IN) :: n_e,t_e,n_i,t_i,omega,omega_e,omega_i, + $ qval,sval,bt,rs,R0,zeff,inpr + REAL(r8),INTENT(IN),OPTIONAL :: inlayfac,inlayfrac + REAL(r8) :: layfac_max,layfac_frac + INTEGER, INTENT(IN) :: mms,nns,mu_i + LOGICAL, INTENT(IN) :: ascii_flag + COMPLEX(r8),INTENT(OUT) :: delta,psi0 + REAL(r8),INTENT(OUT) :: jxb,omega_sol,br_th + TYPE(slayer_diag_type), INTENT(OUT), OPTIONAL :: diag + + INTEGER :: i,inum + INTEGER, DIMENSION(1) :: index + + REAL(r8) :: inQ,inQ_e,inQ_i,inpe,inc_beta,inds,intau,inlu + REAL(r8) :: mrs,nrs,rho,b_l,v_a,Qconv,Q0,delta_n_p, + $ lbeta,tau_i,tau_h,tau_r,tau_v + REAL(r8) :: inQ_min,inQ_max,Q_sol,maxbal + INTEGER :: ipass + INTEGER, PARAMETER :: nref=slayer_nref + REAL(r8) :: xpk,rlo,rhi,rdq,rdqc,xq,bloc,jloc + COMPLEX(r8) :: dloc + +c Eq. (61) term capture. cqs/cdlt/clhs/crhs/cbal/cbrb hold every +c sample of the coarse and refinement scans, cpass its pass tag, +c and iperm the permutation that sorts them by ascending Q. + INTEGER :: j,k,kk + INTEGER, DIMENSION(slayer_nq) :: iperm,cpass + REAL(r8), DIMENSION(slayer_nq) :: cqs,clhs,crhs,cbal,cbrb + COMPLEX(r8), DIMENSION(slayer_nq) :: cdlt + REAL(r8) :: kaphat,xtmp + + REAL(r8), DIMENSION(:), ALLOCATABLE :: inQs,iinQs,jxbl,bal + COMPLEX(r8), DIMENSION(:), ALLOCATABLE :: deltal + CHARACTER(3) :: sn,sm + + parflow_flag=.FALSE. + PeOhmOnly_flag=.TRUE. + riccati_out=.FALSE. + + mrs = real(mms,4) + nrs = real(nns,4) + + ! String representations of the m and n mode numbers + IF (nns<10) THEN + WRITE(UNIT=sn,FMT='(I1)') nns + sn=ADJUSTL(sn) + ELSE + WRITE(UNIT=sn,FMT='(I2)') nns + ENDIF + IF (mms<10) THEN + WRITE(UNIT=sm,FMT='(I1)') mms + sm=ADJUSTL(sm) + ELSEIF (mms<100) THEN + WRITE(UNIT=sm,FMT='(I2)') mms + sm=ADJUSTL(sm) + ELSE + WRITE(UNIT=sm,FMT='(I3)') mms + ENDIF + + inpe=0.0 ! Waybright added this + + tau= t_i/t_e ! ratio of ion to electron temperature + tau_i = 6.6e17*mu_i**0.5*(t_i/1e3)**1.5/(n_e*lnLamb) ! ion colls. + eta= 1.65e-9*lnLamb/(t_e/1e3)**1.5 ! spitzer resistivity (wesson) + rho=(mu_i*m_p)*n_e ! mass density + + b_l=(nrs/mrs)*rs*sval*bt/R0 ! characteristic magnetic field + v_a=b_l/(mu0*rho)**0.5 ! alfven velocity + rho_s=1.02e-4*(mu_i*t_e)**0.5/bt ! ion Lamour by elec. Temp. + + tau_h=R0*(mu0*rho)**0.5/(nns*sval*bt) ! alfven time across surface + tau_r=mu0*rs**2.0/eta ! resistive time scale + tau_v=tau_r/inpr ! rho*rs**2.0/visc ! viscous time scale + + ! this one must be anomalous. calculated back from pr. + visc= rho*rs**2.0/tau_v + + lu=tau_r/tau_h ! Lundquist number + + Qconv=lu**(1.0/3.0)*tau_h ! conversion to Qs based on Cole + + ! note Q depends on Qconv even if omega is fixed. + Q=Qconv*omega + Q_e=-Qconv*omega_e + Q_i=-Qconv*omega_i + + ! This is the most critical parameter + ds=lu**(1.0/3.0)*rho_s/rs ! conversion based on Cole. + + lbeta=(5.0/3.0)*mu0*n_e*chag*(t_e+t_i)/bt**2.0 + c_beta=(lbeta/(1.0+lbeta))**0.5 + + delta_n=lu**(1.0/3.0)/rs ! norm factor for delta primes + + inQ=Q + inQ_e=Q_e + inQ_i=Q_i + inc_beta=c_beta + inds=ds + intau=tau + Q0=Q +c----------------------------------------------------------------------- +c set the layer regularization width. +c +c riccati excises a disc of radius layfac around Q_e, where Im[Delta] +c has a zero and bal=2P(Q0-Q)/lhs therefore has a pole. Without it the +c coarse scan and its refinement walk into that pole and MAXVAL(bal) +c returns a threshold set by the scan spacing rather than by the +c saddle-node bifurcation. gpec_slayer never assigned layfac, so on +c this path the guard was dead. +c +c A fixed width is not safe on every surface: the disc [Q_e-layfac, +c Q_e+layfac] can be a large fraction of the physical branch, and on +c high-m surfaces it can swallow the turning point or Q0 itself -- +c quietly, since a number still comes back. So the width is scaled to +c the accessible branch |Q0-Q_e| and capped: +c +c layfac_frac > 0 : layfac = MIN(layfac_max, layfac_frac*|Q0-Q_e|) +c layfac_frac <= 0: layfac = layfac_max (fixed width) +c layfac_max <= 0: layfac = 0 (guard off) +c +c Exposed through gpec.in so the choice is auditable per run; it is a +c physics judgement, not a constant. +c----------------------------------------------------------------------- + layfac_max=0.02_r8 + IF (PRESENT(inlayfac)) layfac_max=inlayfac + layfac_frac=0.25_r8 + IF (PRESENT(inlayfrac)) layfac_frac=inlayfrac + IF (layfac_max>0.0_r8) THEN + IF (layfac_frac>0.0_r8) THEN + layfac=MIN(layfac_max,layfac_frac*ABS(Q0-inQ_e)) + ELSE + layfac=layfac_max + ENDIF + ELSE + layfac=0.0_r8 + ENDIF +c----------------------------------------------------------------------- +c calculate basic delta, torque, balance, error fields. +c----------------------------------------------------------------------- + delta_n_p=1e-2 + ! kappa_hat of Eq. (61) is implicit in the br_th expression at the + ! end of this routine: sqrt(maxbal/lu*(sval**2/2)) is identically + ! sqrt(maxbal/(lu*kappa_hat)) for kappa_hat=2/sval**2. Named here + ! for output only; it is never used in a physics expression, so + ! the threshold is unchanged. + IF (sval/=0.0_r8) THEN + kaphat=2.0_r8/sval**2.0 + ELSE + kaphat=0.0_r8 + ENDIF + delta=riccati(inQ,inQ_e,inQ_i,inpr,inc_beta,inds,intau,inpe) + psi0=1.0/ABS(delta+delta_n_p) ! a.u. + jxb=-AIMAG(1.0/(delta+delta_n_p)) ! a.u. +c---------------------------------------------------------------------- +c find solutions based on simple torque balance. +c----------------------------------------------------------------------- + IF (Q0>inQ_e) THEN + inQ_max=2.0*Q0 + inQ_min=1.05*inQ_e + ELSE + inQ_max=0.95*inQ_e + IF (Q0>0) THEN + inQ_min=0.8*inQ_i + ELSE + inQ_min=1.5*MINVAL((/Q0,inQ_i/)) + ENDIF + ENDIF + + ! Scan of rotation + inQ_max=10.0 + inQ_min=-10.0 + inum=slayer_inum + ALLOCATE(inQs(0:inum),deltal(0:inum),jxbl(0:inum),bal(0:inum)) + DO i=0,inum + inQs(i)=inQ_min+(REAL(i)/inum)*(inQ_max-inQ_min) + deltal(i)=riccati(inQs(i),inQ_e,inQ_i, + $ inpr,inc_beta,inds,intau,inpe) + jxbl(i)=-AIMAG(1.0/(deltal(i)+delta_n_p)) + bal(i)=2.0*inpr*(Q0-inQs(i))/jxbl(i) + ENDDO + + ! Capture the coarse pass (tag 0). This only reads inQs/deltal/ + ! jxbl/bal, so both the ascii dump and the refinement below are + ! bit for bit unchanged. The Eq. (61) right hand side numerator + ! is recomputed rather than harvested out of the bal expression + ! above; 2.0*inpr*(Q0-inQs(i)) is a pure product chain, so the + ! recomputed value is identical to the one formed inline. + DO i=0,inum + cqs(i+1)=inQs(i) + cdlt(i+1)=deltal(i) + clhs(i+1)=jxbl(i) + crhs(i+1)=2.0*inpr*(Q0-inQs(i)) + cbal(i+1)=bal(i) + cpass(i+1)=0 + ENDDO + + ! Write torque balance curves to file for diagnostic purposes + IF(ascii_flag)THEN + OPEN(UNIT=out_unit,FILE="gpec_slayer_torque_balance_m"// + $ TRIM(sm)//"_n"//TRIM(sn)//".out", + $ STATUS="UNKNOWN") + WRITE(out_unit,'(1x,5(a17))') "inQ","RE(delta)", + $ "IM(delta)","jxb","bal" + DO i=0,inum + WRITE(out_unit,'(1x,5(es17.8e3))') + $ inQs(i),REAL(deltal(i)),AIMAG(deltal(i)),jxbl(i),bal(i) + ENDDO + CLOSE(out_unit) + ENDIF + + ! The coarse scan above gives the overall torque-balance shape + ! and the diagnostic output. The locking "nose" (the maximum of + ! bal) can be a very narrow spike near inQ=Q0, however, and the + ! coarse grid can step right over it, leaving a spuriously + ! negative MAXVAL(bal) and hence a NaN br_th. Bracket the coarse + ! maximum and iteratively refine the scan around the running peak + ! so the nose is resolved regardless of how narrow it is. Exclude + ! non-finite entries (NaN from 0/0, Inf from a near-zero jxbl). + index=MAXLOC(bal,MASK=(bal==bal .AND. ABS(bal)maxbal) THEN + maxbal=bloc + xpk=xq + ENDIF + ENDDO + rlo=xpk-2.0*rdq + rhi=xpk+2.0*rdq + ENDDO + Q_sol=xpk + omega_sol=xpk/Qconv + ! If even the refined nose is non-positive the surface has no + ! finite penetration threshold; floor at zero and warn rather + ! than propagating a NaN into b_crit/Phi_res_crit downstream. + IF (maxbal>0.0_r8) THEN + br_th=sqrt(maxbal/lu*(sval**2.0/2.0)) + ELSE + br_th=0.0_r8 + WRITE(*,'(1x,a,i0,a,i0,a)') + $ "!! WARNING: SLAYER torque balance has no positive "// + $ "maximum at m=",mms,", n=",nns,"; br_th set to 0" + ENDIF +c----------------------------------------------------------------------- +c assemble the Eq. (61) record: b_r/B_phi implied by each balance +c point, then merge the coarse and refined samples onto one +c ascending Q grid so the narrow nose is densely resolved and the +c curve can be interpolated in post processing. +c----------------------------------------------------------------------- + ! Dedicated logarithmic sweep through the Q_e singularity, half + ! the samples on each side, |Q-Q_e| running from slayer_qefar in + ! to slayer_qenear. br_th is already fixed above and these are + ! tagged slayer_qetag, so they are invisible to the peak search. + DO i=1,slayer_nqe/2 + xq=slayer_qefar*(slayer_qenear/slayer_qefar) + $ **(REAL(i-1,r8)/REAL(slayer_nqe/2-1,r8)) + DO j=0,1 + k=(inum+1)*(nref+1)+(i-1)*2+j+1 + IF (j==0) THEN + cqs(k)=inQ_e-xq + ELSE + cqs(k)=inQ_e+xq + ENDIF + cdlt(k)=riccati(cqs(k),inQ_e,inQ_i,inpr, + $ inc_beta,inds,intau,inpe) + clhs(k)=-AIMAG(1.0/(cdlt(k)+delta_n_p)) + crhs(k)=2.0*inpr*(Q0-cqs(k)) + cbal(k)=crhs(k)/clhs(k) + cpass(k)=slayer_qetag + ENDDO + ENDDO + ! deliberately the same expression form as br_th above, so the + ! peak sample reproduces br_th exactly rather than differing in + ! the last bit. + DO k=1,slayer_nq + IF (cbal(k)==cbal(k) .AND. cbal(k)>0.0_r8 + $ .AND. ABS(cbal(k))=1) + IF (cqs(iperm(j))<=xtmp) EXIT + iperm(j+1)=iperm(j) + j=j-1 + ENDDO + iperm(j+1)=kk + ENDDO + IF (PRESENT(diag)) THEN + DO k=1,slayer_nq + kk=iperm(k) + diag%qs(k)=cqs(kk) + diag%dlt(k)=cdlt(kk) + diag%lhs(k)=clhs(kk) + diag%rhs(k)=crhs(kk) + diag%bal(k)=cbal(kk) + diag%brb(k)=cbrb(kk) + diag%kpass(k)=cpass(kk) + ENDDO + ! scalars are taken from the local copies, never from the + ! sglobal_mod globals Q/Q_e/Q_i/ds/tau/c_beta/pr/pe: riccati + ! overwrites those on every call, so by this point the module + ! Q holds the last refinement sample rather than Q0. + diag%alpha=delta_n_p + diag%kaphat=kaphat + diag%slun=lu + diag%prnd=inpr + diag%q0v=Q0 + diag%qcnv=Qconv + diag%qev=inQ_e + diag%qiv=inQ_i + diag%dsv=inds + diag%cbeta=inc_beta + diag%tratio=intau + diag%pev=inpe + diag%lfac=layfac + diag%dnorm=delta_n + diag%rhos=rho_s + diag%etav=eta + diag%viscv=visc + diag%tauh=tau_h + diag%taur=tau_r + diag%tauv=tau_v + diag%taui=tau_i + diag%shr=sval + diag%bl=b_l + diag%va=v_a + diag%rhom=rho + diag%lbet=lbeta + diag%omg=omega + diag%qsol=Q_sol + diag%wsol=omega_sol + diag%brth=br_th + diag%qmn=inQ_min + diag%qmx=inQ_max + IF (maxbal>-HUGE(maxbal)) THEN + diag%mxbal=maxbal + ELSE + diag%mxbal=0.0_r8 + ENDIF + ENDIF + DEALLOCATE(inQs,deltal,jxbl,bal) + + RETURN + END SUBROUTINE gpec_slayer + + END MODULE gslayer_mod diff --git a/src/Tearing/Tearing.jl b/src/Tearing/Tearing.jl index 745a30857..ae3ed8e3c 100644 --- a/src/Tearing/Tearing.jl +++ b/src/Tearing/Tearing.jl @@ -23,12 +23,14 @@ import ..InnerLayer as InnerLayer include("LayerInputs.jl") include("Dispersion/Dispersion.jl") +include("CriticalResonantField/CriticalResonantField.jl") include("Runner/Runner.jl") import .Dispersion as Dispersion +import .CriticalResonantField as CriticalResonantField import .Runner as Runner -export InnerLayer, Dispersion, Runner +export InnerLayer, Dispersion, CriticalResonantField, Runner export build_ggj_inputs end # module Tearing From ba740feebe21bf366d5dc69e4c07831b3bc97f73 Mon Sep 17 00:00:00 2001 From: ebursch <76970916+ebursch@users.noreply.github.com> Date: Sat, 15 Aug 2026 21:28:37 -0400 Subject: [PATCH 2/9] WIP - Testing --- .../CriticalResonantField/bcrit_dev.ipynb | 231 +++++++++++++++++- .../CriticalResonantField/bcrit_dev_ggj.ipynb | 34 ++- 2 files changed, 257 insertions(+), 8 deletions(-) diff --git a/src/Tearing/CriticalResonantField/bcrit_dev.ipynb b/src/Tearing/CriticalResonantField/bcrit_dev.ipynb index a6186408f..78490c308 100644 --- a/src/Tearing/CriticalResonantField/bcrit_dev.ipynb +++ b/src/Tearing/CriticalResonantField/bcrit_dev.ipynb @@ -97,6 +97,223 @@ "id": "4", "metadata": {}, "outputs": [], + "source": [ + "function torque_balance_scan(tb; Qmin=-10.0, Qmax=10.0, n=200)\n", + " Qs = range(Qmin, Qmax; length=n)\n", + " torque_out = [torque_balance_value(tb, q) for q in Qs]\n", + " bal = [x[1] for x in torque_out]\n", + " Δs = [x[2] for x in torque_out]\n", + "\n", + " positive = isfinite.(bal) .& (bal .> 0.0)\n", + "\n", + " if !any(positive)\n", + " return Qs, bal, Float64[], Float64[], NaN, NaN, 0, Δs\n", + " end\n", + "\n", + " i = argmax(bal)\n", + " Qpeak_ind = i\n", + " Qs_positive = Qs[positive]\n", + " bal_positive = bal[positive]\n", + "\n", + " i = argmax(bal_positive)\n", + " Qpeak = Qs_positive[i]\n", + " maxbal = bal_positive[i]\n", + "\n", + " br_crit = sqrt(maxbal / tb.lu * (tb.sval^2 / 2.0))\n", + " return Qs, bal, Qs_positive, bal_positive, Qpeak, br_crit, Qpeak_ind, Δs\n", + "end\n", + "# one-cell scan: x = b_crit, y = Q_0\n", + "Q0_vals = range(-2.0, 2.0; length=60)\n", + "\n", + "bcrit_vals = Float64[]\n", + "locked_flag = Bool[]\n", + "\n", + "for Q0 in Q0_vals\n", + " tbQ = TorqueBalance(\n", + " tb.model,\n", + " tb.params,\n", + " Float64(Q0),\n", + " tb.P,\n", + " tb.delta_n_p,\n", + " tb.lu,\n", + " tb.sval\n", + " )\n", + "\n", + " Qs, bal, Qs_pos, bal_pos, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tbQ; Qmin=-10.0, Qmax=10.0, n=250)\n", + "\n", + " if isempty(bal_pos) || !all(isfinite.(bal_pos)) || maximum(bal_pos) <= 0\n", + " push!(bcrit_vals, NaN)\n", + " push!(locked_flag, false)\n", + " else\n", + " push!(bcrit_vals, brcrit)\n", + " push!(locked_flag, true)\n", + " end\n", + "end\n", + "\n", + "# keep only finite x-values for plotting\n", + "x = bcrit_vals[isfinite.(bcrit_vals)]\n", + "y = Q0_vals[isfinite.(bcrit_vals)]\n", + "locked = locked_flag[isfinite.(bcrit_vals)]\n", + "\n", + "p = scatter(\n", + " x[locked], y[locked],\n", + " label=\"locked\",\n", + " color=:green,\n", + " markersize=5,\n", + " marker=:circle,\n", + " xlabel=\"b_crit\",\n", + " ylabel=\"Q_0\",\n", + " title=\"Locked / unlocked boundary\",\n", + " legend=:topleft\n", + ")\n", + "\n", + "scatter!(\n", + " p,\n", + " x[.!locked], y[.!locked],\n", + " label=\"unlocked\",\n", + " color=:red,\n", + " markersize=5,\n", + " marker=:square\n", + ")\n", + "\n", + "display(p)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5", + "metadata": {}, + "outputs": [], + "source": [ + "import Pkg; Pkg.add(\"DataInterpolations\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6", + "metadata": {}, + "outputs": [], + "source": [ + "using Plots\n", + "using DataInterpolations\n", + "\n", + "default(\n", + " fontfamily=\"Georgia\",\n", + " grid=false,\n", + " linewidth=2,\n", + " guidefontsize=26,\n", + " tickfontsize=18,\n", + " titlefontsize=30,\n", + " legendfontsize=18,\n", + " size=(1200, 800),\n", + " dpi=150\n", + ")\n", + "\n", + "# Build the critical boundary bcrit(Q0)\n", + "Q0_scan = range(-1.0, 4.5; length=80)\n", + "bcrit_curve = Float64[]\n", + "\n", + "for Q0 in Q0_scan\n", + " tbQ = TorqueBalance(\n", + " tb.model,\n", + " tb.params,\n", + " Float64(Q0),\n", + " tb.P,\n", + " tb.delta_n_p,\n", + " tb.lu,\n", + " tb.sval\n", + " )\n", + "\n", + " Qs, bal, Qs_pos, bal_pos, Qpeak, brcrit, Qpeak_ind, Δs =\n", + " torque_balance_scan(tbQ; Qmin=-10.0, Qmax=10.0, n=250)\n", + "\n", + " if isempty(bal_pos) || !all(isfinite.(bal_pos)) || maximum(bal_pos) <= 0\n", + " push!(bcrit_curve, NaN)\n", + " else\n", + " push!(bcrit_curve, brcrit)\n", + " end\n", + "end\n", + "\n", + "ok = isfinite.(bcrit_curve)\n", + "Q0_plot = Q0_scan[ok]\n", + "bcrit_plot = bcrit_curve[ok]\n", + "\n", + "perm = sortperm(Q0_plot)\n", + "Q0_plot = Q0_plot[perm]\n", + "bcrit_plot = bcrit_plot[perm]\n", + "\n", + "# Interpolate the boundary: bcrit = f(Q0)\n", + "curve_itp = LinearInterpolation(bcrit_plot, Q0_plot)\n", + "\n", + "# Full phase-box bounds\n", + "x0 = minimum(bcrit_plot) * 0.8\n", + "x1 = maximum(bcrit_plot) * 1.2\n", + "y0 = minimum(Q0_plot)\n", + "y1 = maximum(Q0_plot)\n", + "\n", + "xvals = range(x0, x1; length=350)\n", + "yvals = range(y0, y1; length=350)\n", + "\n", + "locked_mask = zeros(Float64, length(yvals), length(xvals))\n", + "for iy in eachindex(yvals)\n", + " y = yvals[iy]\n", + " for ix in eachindex(xvals)\n", + " x = xvals[ix]\n", + " # locked when bcrit exceeds the boundary for that Q0\n", + " locked_mask[iy, ix] = x >= curve_itp(y) ? 1.0 : 0.0\n", + " end\n", + "end\n", + "\n", + "p = contourf(\n", + " xvals, yvals, locked_mask',\n", + " levels=[-0.5, 0.5, 1.5],\n", + " c=[:navy, :firebrick],\n", + " colorbar=false,\n", + " xlabel=\"b_crit\",\n", + " ylabel=\"Q_0\",\n", + " title=\"Locked / unlocked region\",\n", + " framestyle=:box,\n", + " xlims=(x0, x1),\n", + " ylims=(y0, y1),\n", + " legend=false\n", + ")\n", + "\n", + "# Critical boundary\n", + "plot!(p, bcrit_plot, Q0_plot; lw=3, color=:black, label=\"critical boundary\")\n", + "\n", + "# Critical point\n", + "cp_idx = argmax(bcrit_plot)\n", + "cp_x = bcrit_plot[cp_idx]\n", + "cp_y = Q0_plot[cp_idx]\n", + "scatter!(p, [cp_x], [cp_y]; color=:gold, marker=:star5, ms=12, label=\"critical point\")\n", + "\n", + "# Single legend block with one entry per category\n", + "plot!(p, [NaN], [NaN]; color=:firebrick, lw=4, label=\"locked\")\n", + "plot!(p, [NaN], [NaN]; color=:navy, lw=4, label=\"unlocked\")\n", + "plot!(p, [NaN], [NaN]; color=:black, lw=3, label=\"critical boundary\")\n", + "scatter!(p, [NaN], [NaN]; color=:gold, marker=:star5, ms=12, label=\"critical point\")\n", + "\n", + "plot!(p; legend=:topright)\n", + "\n", + "display(p)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8", + "metadata": {}, + "outputs": [], "source": [ "# You can substitute any valid SLAYERParameters you already have.\n", "# This is just an example skeleton.\n", @@ -135,7 +352,7 @@ { "cell_type": "code", "execution_count": null, - "id": "5", + "id": "9", "metadata": {}, "outputs": [], "source": [ @@ -158,7 +375,7 @@ { "cell_type": "code", "execution_count": null, - "id": "6", + "id": "10", "metadata": {}, "outputs": [], "source": [ @@ -170,7 +387,7 @@ { "cell_type": "code", "execution_count": null, - "id": "7", + "id": "11", "metadata": {}, "outputs": [], "source": [ @@ -212,7 +429,7 @@ { "cell_type": "code", "execution_count": null, - "id": "8", + "id": "12", "metadata": {}, "outputs": [], "source": [ @@ -224,6 +441,8 @@ "\n", "rhs = (tb.lu * tb.sval^2 / 2) * br_ratio^2\n", "\n", + "\n", + "\n", "println(\"lhs = \", lhs)\n", "println(\"rhs = \", rhs)\n", "println(\"lhs/rhs = \", lhs / rhs)" @@ -232,7 +451,7 @@ { "cell_type": "code", "execution_count": null, - "id": "9", + "id": "13", "metadata": {}, "outputs": [], "source": [ @@ -241,7 +460,7 @@ "T_VISC = [2.0 * tb.P * (tb.Q0 - q) for (q, jxb) in zip(Qs, jxbs)]\n", "br_t = brcrit\n", "println(tb.lu, \" \", tb.sval, \" \", br_t, \" \", p.bt, \" \", tb.delta_n_p)\n", - "T_EM = tb.lu * tb.sval^2/2 * (br_t / p.bt)^2 * jxbs\n", + "T_EM = tb.lu * tb.sval^2/2 * (brcrit)^2 * jxbs\n", "i = Qpeak_ind\n", "println(T_VISC[i]/(tb.lu * tb.sval^2/2 * (brcrit)^2 * jxbs[i]))\n", "println(T_VISC[i] / (tb.lu * tb.sval^2/2 * (brcrit * p.bt)^2 * jxbs[i]))\n", diff --git a/src/Tearing/CriticalResonantField/bcrit_dev_ggj.ipynb b/src/Tearing/CriticalResonantField/bcrit_dev_ggj.ipynb index 94f04beac..a4d02d76f 100644 --- a/src/Tearing/CriticalResonantField/bcrit_dev_ggj.ipynb +++ b/src/Tearing/CriticalResonantField/bcrit_dev_ggj.ipynb @@ -146,9 +146,12 @@ "metadata": {}, "outputs": [], "source": [ - "Qs = range(-5.0, 5.0, length=200)\n", + "Qs = range(-5.0, 5.0, length=20)\n", "\n", - "vals = [torque_balance_value(tb, q) for q in Qs]" + "vals = [torque_balance_value(tb, q) for q in Qs]\n", + "\n", + "# 1m 34.7s for length = 2\n", + "# 46 m for length = 20\n" ] }, { @@ -194,6 +197,33 @@ "\n", "plot(p1, p2, p3, layout=(3,1), size=(800, 1000))" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "10", + "metadata": {}, + "outputs": [], + "source": [ + "p1 = plot(Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", + "plot!(p1, Qs, imag.(Δs), label=\"Im(Δ)\", lw=2)\n", + "xlabel!(p1, \"Q\")\n", + "ylabel!(p1, \"Δ\")\n", + "title!(p1, \"Inner-layer Δ(Q)\")\n", + "\n", + "p2 = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", + "xlabel!(p2, \"Q\")\n", + "ylabel!(p2, \"jxb\")\n", + "title!(p2, \"jxb(Q) = -Im[1/(Δ + δ_n_p)]\")\n", + "\n", + "p3 = plot(Qs, real.(vals), label=\"Re(balance)\", lw=2)\n", + "plot!(p3, Qs, imag.(vals), label=\"Im(balance)\", lw=2)\n", + "xlabel!(p3, \"Q\")\n", + "ylabel!(p3, \"balance\")\n", + "title!(p3, \"2P(Q0-Q)/jxb\")\n", + "\n", + "plot(p1, p2, p3, layout=(3,1), size=(800, 1000))" + ] } ], "metadata": { From ddd54fefb2051d59e65b5e3537fc5d1ce4f91de3 Mon Sep 17 00:00:00 2001 From: ebursch <76970916+ebursch@users.noreply.github.com> Date: Sun, 16 Aug 2026 20:10:59 -0400 Subject: [PATCH 3/9] WIP - In progress bcrit full workflow --- Project.toml | 4 +- benchmarks/benchmark_against_fortran_run.jl | 24 +- ...hmark_coil_ForcingTerms_against_fortran.jl | 121 ++-- benchmarks/benchmark_delta_prime_methods.jl | 4 +- .../benchmark_diiid_ideal_ntv_torque.jl | 4 +- .../benchmark_diiid_kinetic_stability.jl | 4 +- benchmarks/benchmark_riccati_der.jl | 4 +- .../benchmark_solovev_kinetic_stability.jl | 34 +- benchmarks/benchmark_threads.jl | 4 +- benchmarks/compare_gal_vs_el.jl | 6 +- benchmarks/equil_method_comparison.jl | 20 +- benchmarks/equil_numerical_params.jl | 12 +- benchmarks/equil_psihigh_scan.jl | 31 +- benchmarks/equil_psilow_scan.jl | 8 +- benchmarks/equil_spline_comparison.jl | 342 +++++---- benchmarks/plot_xi_eigenmode.jl | 2 +- benchmarks/verify_gal_match.jl | 7 +- docs/make.jl | 4 +- docs/src/forcing_terms.md | 2 +- examples/DIIID-like_SLAYER_example/gpec.toml | 9 + .../analyze_example.jl | 2 +- .../run_imas_example.jl | 8 +- examples/LAR_beta_scan/run_scan.jl | 51 +- examples/LAR_epsilon_scan/run_scan.jl | 51 +- .../Solovev_ideal_example/analyze_example.jl | 11 +- .../analyze_example.jl | 17 +- regression-harness/src/database.jl | 70 +- regression-harness/src/env.jl | 8 +- regression-harness/src/reporter.jl | 6 +- regression-harness/src/types.jl | 5 +- regression-harness/src/utils.jl | 2 +- src/Analysis/Equilibrium.jl | 17 +- src/Analysis/PerturbedEquilibrium.jl | 52 +- src/Analysis/PerturbedEquilibriumModes.jl | 53 +- src/Equilibrium/AnalyticEquilibrium.jl | 120 ++-- src/Equilibrium/DirectEquilibriumArcLength.jl | 11 +- src/Equilibrium/Equilibrium.jl | 44 +- src/Equilibrium/EquilibriumTypes.jl | 35 +- src/Equilibrium/GeometryProfiles.jl | 4 +- src/Equilibrium/ReadEquilibrium.jl | 12 +- src/ForceFreeStates/EulerLagrange.jl | 48 +- .../Galerkin/GalerkinAssembly.jl | 19 +- src/ForceFreeStates/Galerkin/GalerkinGrid.jl | 2 +- src/ForceFreeStates/Galerkin/GalerkinSolve.jl | 4 +- src/ForceFreeStates/Resist.jl | 52 +- src/ForceFreeStates/ResistEval.jl | 85 +-- src/ForceFreeStates/Riccati.jl | 423 +++++------ src/ForceFreeStates/Sing.jl | 8 +- src/ForcingTerms/BiotSavart.jl | 63 +- src/ForcingTerms/CoilGeometry.jl | 12 +- .../coil_geometries/jet_ex_mid.dat | 338 ++++----- src/ForcingTerms/coil_geometries/jtext_l.dat | 162 ++--- src/ForcingTerms/coil_geometries/jtext_m.dat | 162 ++--- src/ForcingTerms/coil_geometries/jtext_u.dat | 162 ++--- .../coil_geometries/mastu_efcc.dat | 338 ++++----- .../coil_geometries/mastu_rmpl.dat | 674 +++++++++--------- .../coil_geometries/mastu_rmpu.dat | 338 ++++----- src/HDF5Schema.jl | 19 +- src/InnerLayer/GGJ/Ray.jl | 2 - src/InnerLayer/InnerLayerInterface.jl | 8 +- src/InnerLayer/SLAYER/LayerInputs.jl | 9 + src/InnerLayer/SLAYER/LayerParameters.jl | 50 +- src/KineticForces/BounceAveraging.jl | 155 ++-- src/KineticForces/EnergyIntegration.jl | 50 +- src/KineticForces/KineticForces.jl | 4 +- src/KineticForces/KineticForcesStructs.jl | 83 ++- src/KineticForces/Output.jl | 12 +- src/KineticForces/PitchIntegration.jl | 68 +- src/KineticForces/Torque.jl | 259 +++---- src/KineticForces/Utils.jl | 4 +- src/LocalStability/Ballooning.jl | 48 +- .../FieldReconstruction.jl | 10 +- .../PerturbedEquilibriumStructs.jl | 21 +- src/PerturbedEquilibrium/Utils.jl | 104 +-- src/Rerun.jl | 19 +- .../CriticalResonantField.jl | 4 +- .../CriticalResonantField/TorqueBalance.jl | 116 ++- .../CriticalResonantField/bcrit_dev.ipynb | 402 ++++------- src/Tearing/Dispersion/BruteForceScan.jl | 22 +- src/Tearing/Dispersion/ContourSearchAMR.jl | 4 +- src/Tearing/Dispersion/CoupledFullMatch.jl | 2 +- .../Dispersion/GrowthRateExtraction.jl | 8 +- src/Tearing/Runner/Control.jl | 41 ++ src/Tearing/Runner/HDF5Output.jl | 34 +- src/Tearing/Runner/Result.jl | 40 +- src/Tearing/Runner/Runner.jl | 9 +- src/Tearing/Runner/run_slayer.jl | 79 ++ src/Tearing/Tearing.jl | 2 + src/Utilities/GridUtilities.jl | 24 +- src/Utilities/HDF5Annotations.jl | 3 +- src/Utilities/PhysicalConstants.jl | 8 +- src/Vacuum/PnQuadCache.jl | 18 +- test/runtests_coordinate_invariant.jl | 30 +- test/runtests_dispersion_amr.jl | 74 +- test/runtests_dispersion_coupled.jl | 64 +- test/runtests_dispersion_coupled_full.jl | 2 +- test/runtests_dispersion_polish.jl | 4 +- test/runtests_dispersion_residual.jl | 24 +- test/runtests_dispersion_scan.jl | 42 +- test/runtests_equil.jl | 22 +- test/runtests_eulerlagrange.jl | 2 +- test/runtests_imas.jl | 34 +- test/runtests_kinetic.jl | 8 +- test/runtests_parallel_integration.jl | 63 +- test/runtests_rerun_from_h5.jl | 6 +- test/runtests_riccati.jl | 4 +- test/runtests_sing.jl | 16 +- test/runtests_tj_analytic.jl | 46 +- 108 files changed, 3299 insertions(+), 2998 deletions(-) diff --git a/Project.toml b/Project.toml index fe2f324d5..658824c00 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "GeneralizedPerturbedEquilibrium" uuid = "462872dd-e066-4d2e-b993-6468b5239634" license = "MIT" -authors = ["Nikolas Logan ", "Jong-Kyu Park ", "Matthew Pharr ", "Jacob Halpern ", "Rithik Banerjee ", "Jaebeom Cho ", "Daniel Burgess ", "Min-Gu Yoo "] +authors = ["Nikolas Logan ", "Jong-Kyu Park ", "Matthew Pharr ", "Jacob Halpern ", "Rithik Banerjee ", "Jaebeom Cho ", "Daniel Burgess ", "Min-Gu Yoo ","Evan Bursch "] version = "0.1.0" [deps] @@ -69,5 +69,3 @@ Statistics = "1" TOML = "1" Test = "1" julia = "1.11" - - diff --git a/benchmarks/benchmark_against_fortran_run.jl b/benchmarks/benchmark_against_fortran_run.jl index 6116a8058..42618bb47 100644 --- a/benchmarks/benchmark_against_fortran_run.jl +++ b/benchmarks/benchmark_against_fortran_run.jl @@ -109,7 +109,7 @@ end function _find_indexed2_float(text::String, name::String, i::Int, j::Int; default=nothing) m = match(Regex( - "\\b$(name)\\s*\\(\\s*$(i)\\s*,\\s*$(j)\\s*\\)\\s*=\\s*([+-]?[\\d.]+(?:[eE][+-]?\\d+)?)", "i"), + "\\b$(name)\\s*\\(\\s*$(i)\\s*,\\s*$(j)\\s*\\)\\s*=\\s*([+-]?[\\d.]+(?:[eE][+-]?\\d+)?)", "i"), text) isnothing(m) ? default : parse(Float64, m.captures[1]) end @@ -548,8 +548,8 @@ function compare_phix( grid = ForcingTerms.sample_boundary_grid(equil, p.mtheta_coil, p.nzeta_coil; psi=psilim) nobs = p.mtheta_coil * p.nzeta_coil - obs_R = zeros(nobs); - obs_phi = zeros(nobs); + obs_R = zeros(nobs) + obs_phi = zeros(nobs) obs_Z = zeros(nobs) for j in 1:p.nzeta_coil, i in 1:p.mtheta_coil idx = i + (j - 1) * p.mtheta_coil @@ -557,8 +557,8 @@ function compare_phix( obs_phi[idx] = grid.phi_grid[j] + grid.phi_offset[i] obs_Z[idx] = grid.Z[i] end - B_R = zeros(nobs); - B_phi = zeros(nobs); + B_R = zeros(nobs) + B_phi = zeros(nobs) B_Z = zeros(nobs) ForcingTerms.compute_biot_savart_boundary!(B_R, B_phi, B_Z, obs_R, obs_phi, obs_Z, coil_sets) bn = zeros(p.mtheta_coil, p.nzeta_coil) @@ -639,9 +639,9 @@ function build_comparison_table(fort, julia, fortran_dir, bench_dir, nn) push!(lines, "") push!(lines, "--- Mercier Criterion ---") - fdi = fort["di"]; + fdi = fort["di"] fdr = fort["dr"] - jdi = julia["di"]; + jdi = julia["di"] jdr = julia["dr"] if !isempty(jdi) && !isempty(fdi) jdi_on_fg = [_interp1(jq_psi, jdi, p) for p in fq_psi] @@ -857,7 +857,7 @@ function build_comparison_table(fort, julia, fortran_dir, bench_dir, nn) end function _interp1(x::AbstractVector, y::AbstractVector, xi::Real) - n = length(x); + n = length(x) n < 2 && return y[1] xi <= x[1] && return y[1] xi >= x[end] && return y[end] @@ -1451,15 +1451,15 @@ function main(argv=ARGS) println() table_lines = build_comparison_table(fort, julia, fortran_dir, bench_dir, p.nn) for line in table_lines - ; - println(line); + + println(line) end table_path = joinpath(bench_dir, "comparison_table.txt") open(table_path, "w") do io for line in table_lines - ; - println(io, line); + + println(io, line) end end println("\nComparison table saved to: ", abspath(table_path)) diff --git a/benchmarks/benchmark_coil_ForcingTerms_against_fortran.jl b/benchmarks/benchmark_coil_ForcingTerms_against_fortran.jl index 22e2b1938..e6c9b60cf 100644 --- a/benchmarks/benchmark_coil_ForcingTerms_against_fortran.jl +++ b/benchmarks/benchmark_coil_ForcingTerms_against_fortran.jl @@ -25,7 +25,7 @@ using NCDatasets using Plots using Printf -const OUTPUT_DIR = joinpath(@__DIR__, "coil_pipeline") +const OUTPUT_DIR = joinpath(@__DIR__, "coil_pipeline") const COIL_DAT_DIR = joinpath(@__DIR__, "..", "src", "ForcingTerms", "coil_geometries") # --------------------------------------------------------------------------- @@ -89,38 +89,38 @@ end function parse_fortran_run(dir::String)::FortranRunParams equil_file = joinpath(dir, "equil.in") - dcon_file = joinpath(dir, "dcon.in") - coil_file = joinpath(dir, "coil.in") + dcon_file = joinpath(dir, "dcon.in") + coil_file = joinpath(dir, "coil.in") isfile(equil_file) || error("equil.in not found in $dir") - isfile(dcon_file) || error("dcon.in not found in $dir") - isfile(coil_file) || error("coil.in not found in $dir") + isfile(dcon_file) || error("dcon.in not found in $dir") + isfile(coil_file) || error("coil.in not found in $dir") - eq_text = _strip_fortran_comments(read(equil_file, String)) - dcon_text = _strip_fortran_comments(read(dcon_file, String)) - coil_text = _strip_fortran_comments(read(coil_file, String)) + eq_text = _strip_fortran_comments(read(equil_file, String)) + dcon_text = _strip_fortran_comments(read(dcon_file, String)) + coil_text = _strip_fortran_comments(read(coil_file, String)) # Equilibrium parameters - eq_type = _find_string(eq_text, "eq_type"; default="efit") - eq_file = _find_string(eq_text, "eq_filename"; default="") - jac_type = _find_string(eq_text, "jac_type"; default="hamada") - psilow = _find_scalar(eq_text, "psilow"; default=1e-4) - psihigh = _find_scalar(eq_text, "psihigh"; default=0.99) - mtheta_eq = _find_int(eq_text, "mtheta"; default=256) + eq_type = _find_string(eq_text, "eq_type"; default="efit") + eq_file = _find_string(eq_text, "eq_filename"; default="") + jac_type = _find_string(eq_text, "jac_type"; default="hamada") + psilow = _find_scalar(eq_text, "psilow"; default=1e-4) + psihigh = _find_scalar(eq_text, "psihigh"; default=0.99) + mtheta_eq = _find_int(eq_text, "mtheta"; default=256) grid_type = _find_string(eq_text, "grid_type"; default="ldp") # Toroidal mode number and m-range expansion - nn = _find_int(dcon_text, "nn"; default=1) - delta_mlow = _find_int(dcon_text, "delta_mlow"; default=8) + nn = _find_int(dcon_text, "nn"; default=1) + delta_mlow = _find_int(dcon_text, "delta_mlow"; default=8) delta_mhigh = _find_int(dcon_text, "delta_mhigh"; default=8) # Coil grid parameters mtheta_coil = _find_int(coil_text, "cmtheta"; default=480) - nzeta_coil = _find_int(coil_text, "cmzeta"; default=40) - machine = _find_string(coil_text, "machine"; default="d3d") - coil_num = _find_int(coil_text, "coil_num"; default=1) + nzeta_coil = _find_int(coil_text, "cmzeta"; default=40) + machine = _find_string(coil_text, "machine"; default="d3d") + coil_num = _find_int(coil_text, "coil_num"; default=1) - coil_names = String[] + coil_names = String[] coil_currents = Vector{Float64}[] for ci in 1:coil_num name = _find_indexed_string(coil_text, "coil_name", ci; default="coil$ci") @@ -135,9 +135,9 @@ function parse_fortran_run(dir::String)::FortranRunParams end return FortranRunParams(eq_type, eq_file, jac_type, psilow, psihigh, mtheta_eq, - grid_type, nn, delta_mlow, delta_mhigh, - mtheta_coil, nzeta_coil, machine, - coil_names, coil_currents) + grid_type, nn, delta_mlow, delta_mhigh, + mtheta_coil, nzeta_coil, machine, + coil_names, coil_currents) end function find_output_nc(dir::String, nn::Int) @@ -177,16 +177,16 @@ end nc_path = find_output_nc(run_dir, p.nn) # Read Fortran output (psilim and Phi_x spectrum) -fortran_m = Int[] -fortran_Phix = Float64[] +fortran_m = Int[] +fortran_Phix = Float64[] fortran_psilim = NaN NCDatasets.Dataset(nc_path, "r") do ds - global fortran_m = Int.(ds["m"][:]) + global fortran_m = Int.(ds["m"][:]) global fortran_psilim = Float64(ds.attrib["psilim"]) phi_x_raw = ds["Phi_x"][:, :] # (mpert, 2); col 1=cos, col 2=sin - global fortran_Phix = sqrt.(phi_x_raw[:, 1].^2 .+ phi_x_raw[:, 2].^2) + global fortran_Phix = sqrt.(phi_x_raw[:, 1] .^ 2 .+ phi_x_raw[:, 2] .^ 2) end -mlow = minimum(fortran_m) +mlow = minimum(fortran_m) mhigh = maximum(fortran_m) @printf " Fortran psilim=%.6f, m=%d:%d\n" fortran_psilim mlow mhigh @@ -196,15 +196,15 @@ mhigh = maximum(fortran_m) println("\n[2/4] Loading equilibrium ...") t_equil = @elapsed begin eq_dict = Dict{String,Any}( - "eq_type" => p.eq_type, - "eq_filename" => p.eq_filename, - "jac_type" => p.jac_type, - "psilow" => p.psilow, - "psihigh" => p.psihigh, - "mtheta" => p.mtheta_equil, - "grid_type" => p.grid_type, + "eq_type" => p.eq_type, + "eq_filename" => p.eq_filename, + "jac_type" => p.jac_type, + "psilow" => p.psilow, + "psihigh" => p.psihigh, + "mtheta" => p.mtheta_equil, + "grid_type" => p.grid_type, "psi_accuracy" => 0.001, - "etol" => 1e-7, + "etol" => 1e-7 ) eq_config = Equilibrium.EquilibriumConfig(eq_dict, run_dir) equil = Equilibrium.setup_equilibrium(eq_config) @@ -223,7 +223,7 @@ for (name, currents) in zip(p.coil_names, p.coil_currents) isfile(dat_path) || error("Coil geometry file not found: $dat_path") raw = read_coil_dat(dat_path) push!(coil_sets, CoilSet(raw.name, raw.ncoil, raw.s, raw.nw, raw.nsec, - raw.x, raw.y, raw.z, Float64.(currents[1:raw.ncoil]))) + raw.x, raw.y, raw.z, Float64.(currents[1:raw.ncoil]))) end for cs in coil_sets @printf " %-10s %d conductors currents: %s A\n" cs.name cs.ncoil string(round.(cs.currents; digits=1)) @@ -231,18 +231,22 @@ end julia_modes = ForcingMode[] bnd_grid = nothing -bn = nothing -t_biot = @elapsed begin +bn = nothing +t_biot = @elapsed begin bnd_grid = sample_boundary_grid(equil, p.mtheta_coil, p.nzeta_coil; psi=fortran_psilim) nobs = p.mtheta_coil * p.nzeta_coil - obs_R = zeros(nobs); obs_phi = zeros(nobs); obs_Z = zeros(nobs) + obs_R = zeros(nobs) + obs_phi = zeros(nobs) + obs_Z = zeros(nobs) for j in 1:p.nzeta_coil, i in 1:p.mtheta_coil idx = i + (j - 1) * p.mtheta_coil - obs_R[idx] = bnd_grid.R[i] + obs_R[idx] = bnd_grid.R[i] obs_phi[idx] = bnd_grid.phi_grid[j] + bnd_grid.phi_offset[i] - obs_Z[idx] = bnd_grid.Z[i] + obs_Z[idx] = bnd_grid.Z[i] end - B_R = zeros(nobs); B_phi = zeros(nobs); B_Z = zeros(nobs) + B_R = zeros(nobs) + B_phi = zeros(nobs) + B_Z = zeros(nobs) compute_biot_savart_boundary!(B_R, B_phi, B_Z, obs_R, obs_phi, obs_Z, coil_sets) bn = zeros(p.mtheta_coil, p.nzeta_coil) project_normal_flux!(bn, B_R, B_Z, bnd_grid) @@ -250,7 +254,7 @@ t_biot = @elapsed begin end @printf " Done in %.1f s, max|Phi_x| = %.3e T·m²\n" t_biot maximum(abs, bn) -julia_m = [md.m for md in sort(julia_modes; by=md -> md.m)] +julia_m = [md.m for md in sort(julia_modes; by=md -> md.m)] julia_amps = abs.([md.amplitude for md in sort(julia_modes; by=md -> md.m)]) # Print comparison table @@ -259,7 +263,7 @@ println(" " * "-"^55) for (jm, ja) in zip(julia_m, julia_amps) k = findfirst(==(jm), fortran_m) if !isnothing(k) - fp = fortran_Phix[k] + fp = fortran_Phix[k] ratio = ja > 1e-40 ? fp / ja : NaN @printf " %3d %12.4e %12.4e %.4f\n" jm ja fp ratio end @@ -272,7 +276,7 @@ println(" Expected ratio ≈ 1.000 for all modes.") println("\n[4/4] Generating figure ...") function step_series(m_vals, amps) - m_ext = [m_vals[1] - 1; m_vals; m_vals[end] + 1] + m_ext = [m_vals[1] - 1; m_vals; m_vals[end] + 1] amp_ext = [0.0; amps; 0.0] return m_ext, amp_ext end @@ -286,19 +290,20 @@ p2 = plot_bn_contour(bn, p.mtheta_coil, p.nzeta_coil; n=p.nn) title!(p2, "Normal flux Φₓ(θ, ζ) at ψ=$(round(fortran_psilim; digits=4))") # Panel 3: Julia vs Fortran Phi_x spectrum -jm_ext, ja_ext = step_series(julia_m, julia_amps) -fm_ext, fa_ext = step_series(fortran_m, fortran_Phix) +jm_ext, ja_ext = step_series(julia_m, julia_amps) +fm_ext, fa_ext = step_series(fortran_m, fortran_Phix) p3 = plot(; xlabel="Poloidal mode m", ylabel="|Phi_x| [T·m²]", - title="Spectrum: Julia vs Fortran (n=$(p.nn))", - legend=:topright) + title="Spectrum: Julia vs Fortran (n=$(p.nn))", + legend=:topright) plot!(p3, jm_ext, ja_ext; seriestype=:steppre, lw=2, color=:blue, - label="Julia ψ=$(round(fortran_psilim; digits=4))") + label="Julia ψ=$(round(fortran_psilim; digits=4))") plot!(p3, fm_ext, fa_ext; seriestype=:steppre, lw=2, color=:orange, - linestyle=:dash, label="Fortran Phi_x") -ylims!(p3, (0, Inf)); xlims!(p3, mlow - 2, mhigh + 2) + linestyle=:dash, label="Fortran Phi_x") +ylims!(p3, (0, Inf)); +xlims!(p3, mlow - 2, mhigh + 2) # Panel 4: Phi_x / Julia ratio -ratio_m = Int[] +ratio_m = Int[] ratio_vals = Float64[] for (jm, ja) in zip(julia_m, julia_amps) k = findfirst(==(jm), fortran_m) @@ -308,8 +313,8 @@ for (jm, ja) in zip(julia_m, julia_amps) end end p4 = plot(; xlabel="Poloidal mode m", ylabel="Phi_x / Julia", - title="Ratio (flat at 1.0 → correct)", - legend=:topright) + title="Ratio (flat at 1.0 → correct)", + legend=:topright) if !isempty(ratio_m) scatter!(p4, ratio_m, ratio_vals; color=:blue, label="ratio", markersize=5) hline!(p4, [1.0]; color=:red, linestyle=:dash, label="expected = 1.0") @@ -318,8 +323,8 @@ xlims!(p4, mlow - 2, mhigh + 2) run_label = basename(run_dir) fig = plot(p1, p2, p3, p4; - layout=(2, 2), size=(1400, 900), - plot_title="$run_label | $(p.machine) n=$(p.nn) psilim=$(round(fortran_psilim; digits=4))") + layout=(2, 2), size=(1400, 900), + plot_title="$run_label | $(p.machine) n=$(p.nn) psilim=$(round(fortran_psilim; digits=4))") out_png = joinpath(OUTPUT_DIR, "coil_pipeline_$(run_label)_n$(p.nn).png") savefig(fig, out_png) diff --git a/benchmarks/benchmark_delta_prime_methods.jl b/benchmarks/benchmark_delta_prime_methods.jl index 917e7c9c5..d005eea7e 100644 --- a/benchmarks/benchmark_delta_prime_methods.jl +++ b/benchmarks/benchmark_delta_prime_methods.jl @@ -32,8 +32,8 @@ function setup_and_run_solovev() intr.wall_settings = GeneralizedPerturbedEquilibrium.Vacuum.WallShapeSettings(; (Symbol(k) => v for (k, v) in inputs["Wall"])...) FFS.sing_lim!(intr, ctrl, equil) - intr.nlow = ctrl.nn_low; - intr.nhigh = ctrl.nn_high; + intr.nlow = ctrl.nn_low + intr.nhigh = ctrl.nn_high intr.npert = 1 FFS.sing_find!(intr, equil) intr.mlow = min(intr.nlow * equil.params.qmin, 0) - 4 - ctrl.delta_mlow diff --git a/benchmarks/benchmark_diiid_ideal_ntv_torque.jl b/benchmarks/benchmark_diiid_ideal_ntv_torque.jl index 7da279b91..92b788afc 100644 --- a/benchmarks/benchmark_diiid_ideal_ntv_torque.jl +++ b/benchmarks/benchmark_diiid_ideal_ntv_torque.jl @@ -35,7 +35,9 @@ const KF = GPE.KineticForces const Eq = GPE.Equilibrium const PE = GPE.PerturbedEquilibrium -"Fortran GPEC DIII-D ideal example run directory, from the environment (no on-disk default)." +""" +Fortran GPEC DIII-D ideal example run directory, from the environment (no on-disk default). +""" default_fortran_dir() = get(() -> error("Set GPEC_FORTRAN_DIIID, or pass the Fortran run directory as the first argument"), ENV, "GPEC_FORTRAN_DIIID") diff --git a/benchmarks/benchmark_diiid_kinetic_stability.jl b/benchmarks/benchmark_diiid_kinetic_stability.jl index 9ae37b6b3..91ab5b172 100644 --- a/benchmarks/benchmark_diiid_kinetic_stability.jl +++ b/benchmarks/benchmark_diiid_kinetic_stability.jl @@ -36,7 +36,9 @@ using GeneralizedPerturbedEquilibrium const GPE = GeneralizedPerturbedEquilibrium const AnalysisFFS = GPE.Analysis.ForceFreeStates -"Fortran GPEC DIII-D kinetic example run directory, from the environment (no on-disk default)." +""" +Fortran GPEC DIII-D kinetic example run directory, from the environment (no on-disk default). +""" default_fortran_dir() = get(() -> error("Set GPEC_FORTRAN_DIIID_DCON, or pass the Fortran run directory as the first argument"), ENV, "GPEC_FORTRAN_DIIID_DCON") diff --git a/benchmarks/benchmark_riccati_der.jl b/benchmarks/benchmark_riccati_der.jl index 6b23c0a81..df083891f 100644 --- a/benchmarks/benchmark_riccati_der.jl +++ b/benchmarks/benchmark_riccati_der.jl @@ -33,8 +33,8 @@ function setup_solovev() intr.wall_settings = GeneralizedPerturbedEquilibrium.Vacuum.WallShapeSettings(; (Symbol(k) => v for (k, v) in inputs["Wall"])...) FFS.sing_lim!(intr, ctrl, equil) - intr.nlow = ctrl.nn_low; - intr.nhigh = ctrl.nn_high; + intr.nlow = ctrl.nn_low + intr.nhigh = ctrl.nn_high intr.npert = 1 FFS.sing_find!(intr, equil) intr.mlow = min(intr.nlow * equil.params.qmin, 0) - 4 - ctrl.delta_mlow diff --git a/benchmarks/benchmark_solovev_kinetic_stability.jl b/benchmarks/benchmark_solovev_kinetic_stability.jl index c942a20c6..43b3ba25d 100644 --- a/benchmarks/benchmark_solovev_kinetic_stability.jl +++ b/benchmarks/benchmark_solovev_kinetic_stability.jl @@ -43,10 +43,10 @@ using HDF5 using GeneralizedPerturbedEquilibrium const GPE = GeneralizedPerturbedEquilibrium -const REPO = normpath(joinpath(@__DIR__, "..")) -const JULIA_FIXTURE = joinpath(REPO, "test", "test_data", "regression_solovev_kinetic_calculated") -const FORTRAN_DCON = get(ENV, "GPEC_FORTRAN_DCON", "") -const FORTRAN_SOLDIR = get(ENV, "GPEC_FORTRAN_SOLDIR", "") +const REPO = normpath(joinpath(@__DIR__, "..")) +const JULIA_FIXTURE = joinpath(REPO, "test", "test_data", "regression_solovev_kinetic_calculated") +const FORTRAN_DCON = get(ENV, "GPEC_FORTRAN_DCON", "") +const FORTRAN_SOLDIR = get(ENV, "GPEC_FORTRAN_SOLDIR", "") _p(args...) = (println(stderr, args...); flush(stderr)) @@ -90,35 +90,35 @@ function build_matched_fortran_deck(workdir::String) end gpec = TOML.parsefile(joinpath(JULIA_FIXTURE, "gpec.toml")) - eq = gpec["Equilibrium"] - ffs = gpec["ForceFreeStates"] - kf = get(gpec, "KineticForces", Dict{String,Any}()) + eq = gpec["Equilibrium"] + ffs = gpec["ForceFreeStates"] + kf = get(gpec, "KineticForces", Dict{String,Any}()) # equil.in — grid + coordinate settings to match the Julia [Equilibrium] block. eqin = joinpath(workdir, "equil.in") - replace_namelist_value!(eqin, "psilow", string(eq["psilow"])) + replace_namelist_value!(eqin, "psilow", string(eq["psilow"])) replace_namelist_value!(eqin, "psihigh", string(eq["psihigh"])) - replace_namelist_value!(eqin, "mpsi", string(eq["mpsi"])) - replace_namelist_value!(eqin, "mtheta", string(eq["mtheta"])) + replace_namelist_value!(eqin, "mpsi", string(eq["mpsi"])) + replace_namelist_value!(eqin, "mtheta", string(eq["mtheta"])) # dcon.in — kinetic flags already match; align mode band, edge truncation, n. dconin = joinpath(workdir, "dcon.in") - replace_namelist_value!(dconin, "nn", string(ffs["nn_low"])) - replace_namelist_value!(dconin, "delta_mlow", string(get(ffs, "delta_mlow", 0))) + replace_namelist_value!(dconin, "nn", string(ffs["nn_low"])) + replace_namelist_value!(dconin, "delta_mlow", string(get(ffs, "delta_mlow", 0))) replace_namelist_value!(dconin, "delta_mhigh", string(get(ffs, "delta_mhigh", 0))) - replace_namelist_value!(dconin, "qlow", string(ffs["qlow"])) - replace_namelist_value!(dconin, "qhigh", string(ffs["qhigh"])) + replace_namelist_value!(dconin, "qlow", string(ffs["qlow"])) + replace_namelist_value!(dconin, "qhigh", string(ffs["qhigh"])) replace_namelist_value!(dconin, "singfac_min", string(ffs["singfac_min"])) # Julia set_psilim_via_dmlim defaults true (sas_flag) with dmlim 0.2. replace_namelist_value!(dconin, "sas_flag", "t") - replace_namelist_value!(dconin, "dmlim", "0.2") + replace_namelist_value!(dconin, "dmlim", "0.2") # pentrc.in — bounce harmonics + species; defaults mirror KineticForcesControl. pentin = joinpath(workdir, "pentrc.in") - replace_namelist_value!(pentin, "nl", string(get(kf, "nl", 1))) + replace_namelist_value!(pentin, "nl", string(get(kf, "nl", 1))) replace_namelist_value!(pentin, "nutype", "\"" * string(get(kf, "nutype", "harmonic")) * "\"") replace_namelist_value!(pentin, "f0type", "\"" * string(get(kf, "f0type", "maxwellian")) * "\"") - replace_namelist_value!(pentin, "nufac", string(get(kf, "nufac", 1))) + replace_namelist_value!(pentin, "nufac", string(get(kf, "nufac", 1))) replace_namelist_value!(pentin, "kinetic_file", "\"kinetic.txt\"") # kinetic.txt — Fortran readtable wants a title line then numeric rows; the diff --git a/benchmarks/benchmark_threads.jl b/benchmarks/benchmark_threads.jl index 96e37236a..1abd8a3d4 100644 --- a/benchmarks/benchmark_threads.jl +++ b/benchmarks/benchmark_threads.jl @@ -21,8 +21,8 @@ function run_ffs(ex; integrator) intr.wall_settings = GeneralizedPerturbedEquilibrium.Vacuum.WallShapeSettings(; (Symbol(k) => v for (k, v) in inputs["Wall"])...) GeneralizedPerturbedEquilibrium.ForceFreeStates.sing_lim!(intr, ctrl, equil) - intr.nlow = ctrl.nn_low; - intr.nhigh = ctrl.nn_high; + intr.nlow = ctrl.nn_low + intr.nhigh = ctrl.nn_high intr.npert = 1 GeneralizedPerturbedEquilibrium.ForceFreeStates.sing_find!(intr, equil) intr.mlow = min(intr.nlow * equil.params.qmin, 0) - 4 - ctrl.delta_mlow diff --git a/benchmarks/compare_gal_vs_el.jl b/benchmarks/compare_gal_vs_el.jl index 98c8e82ef..5b695fb0e 100644 --- a/benchmarks/compare_gal_vs_el.jl +++ b/benchmarks/compare_gal_vs_el.jl @@ -43,14 +43,14 @@ xiE = reduce(hcat, (u1[:, :, ip] * cEL for ip in 1:size(u1, 3))) # (mpert, nE) psiGk = psiG xiG = reduce(hcat, (gxi[:, :, ip] * w for ip in eachindex(psiG))) # (mpert, nGk) -ms = mlow .+ (0:mpert-1) +ms = mlow .+ (0:(mpert-1)) peak = [maximum(abs, @view xiE[i, :]) for i in 1:mpert] order = sortperm(peak; rev=true) ndom = min(5, mpert) # quantitative bulk agreement on the dominant harmonic (linear-interp EL onto gal grid, off rationals/edge) -lininterp(xq, x, y) = (j = clamp(searchsortedlast(x, xq), 1, length(x) - 1); -t = (xq - x[j]) / (x[j+1] - x[j]); y[j] * (1 - t) + y[j+1] * t) +lininterp(xq, x, y) = (j=clamp(searchsortedlast(x, xq), 1, length(x) - 1); + t=(xq - x[j]) / (x[j+1] - x[j]); y[j] * (1 - t) + y[j+1] * t) idom = order[1] inbulk(p) = 0.1 <= p <= 0.92 && all(abs(p - ps) > 8e-3 for ps in sing_psi) sel = [ip for ip in eachindex(psiGk) if inbulk(psiGk[ip])] diff --git a/benchmarks/equil_method_comparison.jl b/benchmarks/equil_method_comparison.jl index 450423d6a..151dadd72 100644 --- a/benchmarks/equil_method_comparison.jl +++ b/benchmarks/equil_method_comparison.jl @@ -21,7 +21,7 @@ using GeneralizedPerturbedEquilibrium.Equilibrium using TOML, Printf, Statistics example_path = length(ARGS) > 0 ? ARGS[1] : joinpath(@__DIR__, "../examples/DIIID-like_ideal_example") -config_path = joinpath(example_path, "gpec.toml") +config_path = joinpath(example_path, "gpec.toml") psihigh_override = length(ARGS) > 1 ? parse(Float64, ARGS[2]) : nothing println("=" ^ 65) @@ -58,10 +58,10 @@ for method in methods success = false end results[method] = Dict( - "success" => success, - "pe" => pe, - "runtime" => (t1 + t2) / 2.0, - "config" => cfg + "success" => success, + "pe" => pe, + "runtime" => (t1 + t2) / 2.0, + "config" => cfg ) success && @printf(" Runtime (avg 2 warm): %.3f s\n", (t1 + t2) / 2.0) end @@ -105,7 +105,7 @@ for method in methods results[method]["success"] || continue Δq = abs.([q_vals[method][i] - efit_q_interp(psi_nodes[i]) for i in 1:length(psi_nodes)]) @printf(" |q_%s - q_efit| (ψ<0.95): max=%.2e rms=%.2e\n", - method, maximum(Δq[mask_mid]), sqrt(mean(Δq[mask_mid].^2))) + method, maximum(Δq[mask_mid]), sqrt(mean(Δq[mask_mid] .^ 2))) end # ─── Roundtrip error ───────────────────────────────────────────────────────── @@ -123,15 +123,15 @@ for method in methods psio = pe.psio psi_xs = pe.rzphi_xs psi_ys = pe.rzphi_ys - mpsi = length(psi_xs) - 1 + mpsi = length(psi_xs) - 1 mtheta = length(psi_ys) - 1 errors = Float64[] - for ipsi in 1:5:mpsi+1 + for ipsi in 1:5:(mpsi+1) ψ_target = psi_xs[ipsi] - for itheta in 1:8:mtheta+1 + for itheta in 1:8:(mtheta+1) θ = psi_ys[itheta] - r2 = pe.rzphi_rsquared((ψ_target, θ)) + r2 = pe.rzphi_rsquared((ψ_target, θ)) off = pe.rzphi_offset((ψ_target, θ)) rfac = sqrt(max(r2, 0.0)) η = 2π * (θ + off) diff --git a/benchmarks/equil_numerical_params.jl b/benchmarks/equil_numerical_params.jl index f80f0f64c..f37376745 100644 --- a/benchmarks/equil_numerical_params.jl +++ b/benchmarks/equil_numerical_params.jl @@ -21,26 +21,26 @@ using GeneralizedPerturbedEquilibrium.Equilibrium using TOML, Printf, Statistics example_path = length(ARGS) > 0 ? ARGS[1] : joinpath(@__DIR__, "../examples/DIIID-like_ideal_example") -config_path = joinpath(example_path, "gpec.toml") +config_path = joinpath(example_path, "gpec.toml") function make_config(path, eq_type, mpsi, mtheta) raw = TOML.parsefile(path) raw["Equilibrium"]["eq_type"] = eq_type - raw["Equilibrium"]["mpsi"] = mpsi - raw["Equilibrium"]["mtheta"] = mtheta + raw["Equilibrium"]["mpsi"] = mpsi + raw["Equilibrium"]["mtheta"] = mtheta return Equilibrium.EquilibriumConfig(raw["Equilibrium"], dirname(path)) end function roundtrip_error(pe, raw_profile) psi_xs = pe.rzphi_xs - psio = pe.psio + psio = pe.psio mtheta = length(pe.rzphi_ys) - 1 errors = Float64[] for ipsi in 1:4:length(psi_xs) ψ = psi_xs[ipsi] - for itheta in 1:8:mtheta+1 + for itheta in 1:8:(mtheta+1) θ = pe.rzphi_ys[itheta] - r2 = pe.rzphi_rsquared((ψ, θ)) + r2 = pe.rzphi_rsquared((ψ, θ)) off = pe.rzphi_offset((ψ, θ)) rfac = sqrt(max(r2, 0.0)) η = 2π * (θ + off) diff --git a/benchmarks/equil_psihigh_scan.jl b/benchmarks/equil_psihigh_scan.jl index 56f6e9ec6..99788b281 100644 --- a/benchmarks/equil_psihigh_scan.jl +++ b/benchmarks/equil_psihigh_scan.jl @@ -29,7 +29,7 @@ using GeneralizedPerturbedEquilibrium.Equilibrium using TOML, Printf, Statistics, HDF5 example_path = length(ARGS) > 0 ? ARGS[1] : joinpath(@__DIR__, "../examples/DIIID-like_ideal_example") -config_path = joinpath(example_path, "gpec.toml") +config_path = joinpath(example_path, "gpec.toml") psihigh_values = [0.980, 0.985, 0.990, 0.993, 0.995, 0.996, 0.997, 0.998, 0.999, 0.9995, 0.9999, 1.0] methods = ["efit", "efit_arclength", "efit_by_inversion"] @@ -121,9 +121,9 @@ for method in methods for ipsi in 1:length(psi_xs) psi_xs[ipsi] < 0.90 && continue ψ = psi_xs[ipsi] - for itheta in 1:8:mtheta+1 + for itheta in 1:8:(mtheta+1) θ = pe.rzphi_ys[itheta] - r2 = pe.rzphi_rsquared((ψ, θ)) + r2 = pe.rzphi_rsquared((ψ, θ)) off = pe.rzphi_offset((ψ, θ)) rfac = sqrt(max(r2, 0.0)) η = 2π * (θ + off) @@ -161,13 +161,16 @@ for method in methods isnan(q_at_psihigh) ? -1.0 : q_at_psihigh, et1_str) - push!(rows, ( - method=method, psihigh=psihigh, success=success, runtime=runtime, - roundtrip_max_edge=roundtrip_max_edge, - q_mono_violations_edge=q_mono_violations_edge, - q_at_psihigh=q_at_psihigh, q_edge_slope=q_edge_slope, - et1=et1, error_msg=err_msg - )) + push!( + rows, + ( + method=method, psihigh=psihigh, success=success, runtime=runtime, + roundtrip_max_edge=roundtrip_max_edge, + q_mono_violations_edge=q_mono_violations_edge, + q_at_psihigh=q_at_psihigh, q_edge_slope=q_edge_slope, + et1=et1, error_msg=err_msg + ) + ) end end @@ -198,9 +201,11 @@ println("et[1] vs psihigh (free-boundary stability eigenvalue):") println(" (positive = stable, negative = unstable)") @printf(" %-22s %s\n", "psihigh", join([@sprintf("%-22s", m) for m in methods])) for psihigh in psihigh_values - vals = [let r = findfirst(x -> x.method == m && x.psihigh == psihigh, rows) - r === nothing || isnan(rows[r].et1) ? " -" : @sprintf("%+.4f", rows[r].et1) - end for m in methods] + vals = [ + let r = findfirst(x -> x.method == m && x.psihigh == psihigh, rows) + r === nothing || isnan(rows[r].et1) ? " -" : @sprintf("%+.4f", rows[r].et1) + end for m in methods + ] @printf(" %-22.4f %s\n", psihigh, join([@sprintf("%-22s", v) for v in vals])) end println() diff --git a/benchmarks/equil_psilow_scan.jl b/benchmarks/equil_psilow_scan.jl index ff5902b7b..1129d5ee1 100644 --- a/benchmarks/equil_psilow_scan.jl +++ b/benchmarks/equil_psilow_scan.jl @@ -19,7 +19,7 @@ using GeneralizedPerturbedEquilibrium.Equilibrium using TOML, Printf, Statistics example_path = length(ARGS) > 0 ? ARGS[1] : joinpath(@__DIR__, "../examples/DIIID-like_ideal_example") -config_path = joinpath(example_path, "gpec.toml") +config_path = joinpath(example_path, "gpec.toml") psilow_values = [1e-1, 5e-2, 1e-2, 5e-3, 1e-3, 5e-4, 1e-4] methods = ["efit", "efit_arclength", "efit_by_inversion"] @@ -82,7 +82,7 @@ for method in methods raw_profile = Equilibrium.read_efit(cfg) psi_xs = pe.rzphi_xs mtheta = length(pe.rzphi_ys) - 1 - psio = pe.psio + psio = pe.psio # q0 extrapolated to axis (linear from innermost two grid points) q1 = pe.profiles.q_spline.y[1] @@ -94,9 +94,9 @@ for method in methods for ipsi in 1:length(psi_xs) psi_xs[ipsi] > 0.10 && break ψ = psi_xs[ipsi] - for itheta in 1:8:mtheta+1 + for itheta in 1:8:(mtheta+1) θ = pe.rzphi_ys[itheta] - r2 = pe.rzphi_rsquared((ψ, θ)) + r2 = pe.rzphi_rsquared((ψ, θ)) off = pe.rzphi_offset((ψ, θ)) rfac = sqrt(max(r2, 0.0)) η = 2π * (θ + off) diff --git a/benchmarks/equil_spline_comparison.jl b/benchmarks/equil_spline_comparison.jl index 4cf5337e2..a0ea0bdc0 100644 --- a/benchmarks/equil_spline_comparison.jl +++ b/benchmarks/equil_spline_comparison.jl @@ -27,9 +27,9 @@ using TOML, Printf, Statistics, Plots # ─── CLI arguments ───────────────────────────────────────────────────────────── example_path = length(ARGS) > 0 ? ARGS[1] : - joinpath(@__DIR__, "../examples/DIIID-like_ideal_example") + joinpath(@__DIR__, "../examples/DIIID-like_ideal_example") psihigh_arg = length(ARGS) > 1 ? parse(Float64, ARGS[2]) : 0.997 -config_path = joinpath(example_path, "gpec.toml") +config_path = joinpath(example_path, "gpec.toml") println("=" ^ 70) println("Equilibrium Spline Comparison: efit / efit_arclength / efit_by_inversion") @@ -46,38 +46,38 @@ println("Output : $outdir\n") # ─── Config factory ──────────────────────────────────────────────────────────── function make_config(path::String, eq_type::String, psihigh::Float64) raw = TOML.parsefile(path) - raw["Equilibrium"]["eq_type"] = eq_type + raw["Equilibrium"]["eq_type"] = eq_type raw["Equilibrium"]["psihigh"] = psihigh return Equilibrium.EquilibriumConfig(raw["Equilibrium"], dirname(path)) end # ─── Load all three equilibria ───────────────────────────────────────────────── # efit is the reference; efit_arclength and efit_by_inversion are compared to it. -ref_method = "efit" -compare_methods = ["efit_arclength", "efit_by_inversion"] -all_methods = vcat(ref_method, compare_methods) +ref_method = "efit" +compare_methods = ["efit_arclength", "efit_by_inversion"] +all_methods = vcat(ref_method, compare_methods) method_color = Dict( - "efit" => :blue, - "efit_arclength" => :darkorange, - "efit_by_inversion" => :red, + "efit" => :blue, + "efit_arclength" => :darkorange, + "efit_by_inversion" => :red ) method_style = Dict( - "efit" => :solid, - "efit_arclength" => :dash, - "efit_by_inversion" => :dot, + "efit" => :solid, + "efit_arclength" => :dash, + "efit_by_inversion" => :dot ) method_label = Dict( - "efit" => "efit", - "efit_arclength" => "efit_arclength", - "efit_by_inversion" => "efit_by_inv", + "efit" => "efit", + "efit_arclength" => "efit_arclength", + "efit_by_inversion" => "efit_by_inv" ) diff_color = Dict( - "efit_arclength" => :darkorange, - "efit_by_inversion" => :red, + "efit_arclength" => :darkorange, + "efit_by_inversion" => :red ) -pes = Dict{String, Any}() +pes = Dict{String,Any}() for m in all_methods println("--- Running: $m ---") cfg = make_config(config_path, m, psihigh_arg) @@ -94,22 +94,26 @@ isempty(failed) || println("Skipping failed methods in comparisons: $(join(faile haskey(pes, ref_method) || error("Reference method '$ref_method' failed — cannot continue.") pe_ref = pes[ref_method] -all_methods = filter(m -> haskey(pes, m), all_methods) +all_methods = filter(m -> haskey(pes, m), all_methods) compare_methods_active = filter(m -> haskey(pes, m), compare_methods) # ─── Helpers ─────────────────────────────────────────────────────────────────── -"Convert (ψ, θ) straight-field-line coordinates → (R, Z) physical coordinates." +""" +Convert (ψ, θ) straight-field-line coordinates → (R, Z) physical coordinates. +""" function psi_theta_to_RZ(pe, psi, theta) - r2 = pe.rzphi_rsquared((psi, theta)) - off = pe.rzphi_offset((psi, theta)) + r2 = pe.rzphi_rsquared((psi, theta)) + off = pe.rzphi_offset((psi, theta)) rfac = sqrt(max(r2, 0.0)) - η = 2π * (theta + off) - R = pe.ro + rfac * cos(η) - Z = pe.zo + rfac * sin(η) + η = 2π * (theta + off) + R = pe.ro + rfac * cos(η) + Z = pe.zo + rfac * sin(η) return R, Z end -"Compute the full (R, Z) trace of each flux surface in psi_vals." +""" +Compute the full (R, Z) trace of each flux surface in psi_vals. +""" function flux_surface_RZ(pe, psi_vals, theta_range) R_all = [Float64[] for _ in 1:length(psi_vals)] Z_all = [Float64[] for _ in 1:length(psi_vals)] @@ -130,7 +134,7 @@ end psi_lo = pe_ref.rzphi_xs[1] psi_hi = pe_ref.rzphi_xs[end] mpsi_eval = 8 * (length(pe_ref.rzphi_xs) - 1) -psi_full = psi_lo .+ (psi_hi - psi_lo) .* sin.(range(0.0, 1.0; length=mpsi_eval+1) .* (π/2)).^2 +psi_full = psi_lo .+ (psi_hi - psi_lo) .* sin.(range(0.0, 1.0; length=mpsi_eval+1) .* (π/2)) .^ 2 mask_core = psi_full .< 0.10 mask_edge = psi_full .> 0.98 @@ -148,16 +152,16 @@ println("1. 1D Profile Comparisons") println("=" ^ 70) profile_specs = [ - ("F (2π·R·Bₜ)", pe -> pe.profiles.F_spline), - ("μ₀·P", pe -> pe.profiles.P_spline), - ("dV/dψ", pe -> pe.profiles.dVdpsi_spline), - ("q", pe -> pe.profiles.q_spline), + ("F (2π·R·Bₜ)", pe -> pe.profiles.F_spline), + ("μ₀·P", pe -> pe.profiles.P_spline), + ("dV/dψ", pe -> pe.profiles.dVdpsi_spline), + ("q", pe -> pe.profiles.q_spline) ] profile_fnames = ["profile_F", "profile_P", "profile_dVdpsi", "profile_q"] for (idx, (pname, spl_getter)) in enumerate(profile_specs) spl_ref = spl_getter(pe_ref) - y_ref = [spl_ref(ψ) for ψ in psi_full] + y_ref = [spl_ref(ψ) for ψ in psi_full] p_full = plot(psi_full, y_ref; lw=2, color=method_color[ref_method], ls=method_style[ref_method], label=method_label[ref_method], @@ -187,8 +191,8 @@ for (idx, (pname, spl_getter)) in enumerate(profile_specs) for m in compare_methods_active spl_m = spl_getter(pes[m]) - y_m = [spl_m(ψ) for ψ in psi_full] - Δy = y_ref .- y_m + y_m = [spl_m(ψ) for ψ in psi_full] + Δy = y_ref .- y_m plot!(p_full, psi_full, y_m; lw=1.5, color=method_color[m], ls=method_style[m], label=method_label[m]) @@ -227,66 +231,66 @@ z_global_grid = Float64[] r_zoom_grid_vis = Float64[] z_zoom_grid_vis = Float64[] if haskey(pes, "efit_by_inversion") -let - global r_global_grid, z_global_grid, r_zoom_grid_vis, z_zoom_grid_vis - cfg_inv = make_config(config_path, "efit_by_inversion", psihigh_arg) - raw_inv = Equilibrium.read_efit(cfg_inv) - ro_g, zo_g = pes["efit_by_inversion"].ro, pes["efit_by_inversion"].zo - psio_g = raw_inv.psio - psilow_g = cfg_inv.psilow - topology_g = Equilibrium.classify_topology(raw_inv, psio_g) - - ψ_RR = abs(raw_inv.psi_in((ro_g, zo_g); deriv=DerivOp(2, 0))) - ψ_ZZ = abs(raw_inv.psi_in((ro_g, zo_g); deriv=DerivOp(0, 2))) - a_low_g = min(sqrt(2 * psilow_g * psio_g / ψ_RR), sqrt(2 * psilow_g * psio_g / ψ_ZZ)) - - nw_g = length(raw_inv.psi_in_xs) - nh_g = length(raw_inv.psi_in_ys) - β_r_g, β_z_g = 2.0, 2.0 - refine_g = 5 - - nr_g = max(4, round(Int, refine_g * nw_g)) - nz_g = max(4, round(Int, refine_g * nh_g)) - r_g = Equilibrium.make_stretched_r_grid(raw_inv.rmin, raw_inv.rmax, ro_g, nr_g, β_r_g) - z_g = Equilibrium.make_stretched_z_grid(raw_inv.zmin, raw_inv.zmax, zo_g, nz_g, topology_g, β_z_g) - - iro_g = clamp(searchsortedfirst(r_g, ro_g), 2, length(r_g)) - izo_g = clamp(searchsortedfirst(z_g, zo_g), 2, length(z_g)) - dR_ax = r_g[iro_g] - r_g[iro_g - 1] - dZ_ax = z_g[izo_g] - z_g[izo_g - 1] - sc_r = max(1, ceil(Int, dR_ax / (0.2 * a_low_g))) - sc_z = max(1, ceil(Int, dZ_ax / (0.2 * a_low_g))) - if sc_r > 1 - nr_g = (nr_g - 1) * sc_r + 1 - r_g = Equilibrium.make_stretched_r_grid(raw_inv.rmin, raw_inv.rmax, ro_g, nr_g, β_r_g) + let + global r_global_grid, z_global_grid, r_zoom_grid_vis, z_zoom_grid_vis + cfg_inv = make_config(config_path, "efit_by_inversion", psihigh_arg) + raw_inv = Equilibrium.read_efit(cfg_inv) + ro_g, zo_g = pes["efit_by_inversion"].ro, pes["efit_by_inversion"].zo + psio_g = raw_inv.psio + psilow_g = cfg_inv.psilow + topology_g = Equilibrium.classify_topology(raw_inv, psio_g) + + ψ_RR = abs(raw_inv.psi_in((ro_g, zo_g); deriv=DerivOp(2, 0))) + ψ_ZZ = abs(raw_inv.psi_in((ro_g, zo_g); deriv=DerivOp(0, 2))) + a_low_g = min(sqrt(2 * psilow_g * psio_g / ψ_RR), sqrt(2 * psilow_g * psio_g / ψ_ZZ)) + + nw_g = length(raw_inv.psi_in_xs) + nh_g = length(raw_inv.psi_in_ys) + β_r_g, β_z_g = 2.0, 2.0 + refine_g = 5 + + nr_g = max(4, round(Int, refine_g * nw_g)) + nz_g = max(4, round(Int, refine_g * nh_g)) + r_g = Equilibrium.make_stretched_r_grid(raw_inv.rmin, raw_inv.rmax, ro_g, nr_g, β_r_g) + z_g = Equilibrium.make_stretched_z_grid(raw_inv.zmin, raw_inv.zmax, zo_g, nz_g, topology_g, β_z_g) + iro_g = clamp(searchsortedfirst(r_g, ro_g), 2, length(r_g)) - dR_ax = r_g[iro_g] - r_g[iro_g - 1] - end - if sc_z > 1 - nz_g = (nz_g - 1) * sc_z + 1 - z_g = Equilibrium.make_stretched_z_grid(raw_inv.zmin, raw_inv.zmax, zo_g, nz_g, topology_g, β_z_g) izo_g = clamp(searchsortedfirst(z_g, zo_g), 2, length(z_g)) - dZ_ax = z_g[izo_g] - z_g[izo_g - 1] + dR_ax = r_g[iro_g] - r_g[iro_g-1] + dZ_ax = z_g[izo_g] - z_g[izo_g-1] + sc_r = max(1, ceil(Int, dR_ax / (0.2 * a_low_g))) + sc_z = max(1, ceil(Int, dZ_ax / (0.2 * a_low_g))) + if sc_r > 1 + nr_g = (nr_g - 1) * sc_r + 1 + r_g = Equilibrium.make_stretched_r_grid(raw_inv.rmin, raw_inv.rmax, ro_g, nr_g, β_r_g) + iro_g = clamp(searchsortedfirst(r_g, ro_g), 2, length(r_g)) + dR_ax = r_g[iro_g] - r_g[iro_g-1] + end + if sc_z > 1 + nz_g = (nz_g - 1) * sc_z + 1 + z_g = Equilibrium.make_stretched_z_grid(raw_inv.zmin, raw_inv.zmax, zo_g, nz_g, topology_g, β_z_g) + izo_g = clamp(searchsortedfirst(z_g, zo_g), 2, length(z_g)) + dZ_ax = z_g[izo_g] - z_g[izo_g-1] + end + r_global_grid = r_g + z_global_grid = z_g + + d_max_g = max(dR_ax, dZ_ax) + threshold_g = (10 * d_max_g)^2 * max(ψ_RR, ψ_ZZ) / (2 * psio_g) + psi_zoom_max = 9 * threshold_g + a_zoom_r = sqrt(2 * psi_zoom_max * psio_g / ψ_RR) * 1.2 + a_zoom_z = sqrt(2 * psi_zoom_max * psio_g / ψ_ZZ) * 1.2 + sinh_β = sinh(β_r_g) + nr_z = max(200, ceil(Int, 8 * β_r_g * a_zoom_r * 10 / (sinh_β * a_low_g))) + nz_z = max(200, ceil(Int, 8 * β_r_g * a_zoom_z * 10 / (sinh_β * a_low_g))) + r_zoom_grid_vis = Equilibrium.make_stretched_r_grid( + max(raw_inv.rmin, ro_g - a_zoom_r), min(raw_inv.rmax, ro_g + a_zoom_r), + ro_g, nr_z, β_r_g) + z_zoom_grid_vis = Equilibrium.make_stretched_r_grid( + max(raw_inv.zmin, zo_g - a_zoom_z), min(raw_inv.zmax, zo_g + a_zoom_z), + zo_g, nz_z, β_r_g) + println(" Grid vis: global $(nr_g)×$(nz_g), zoom $(nr_z)×$(nz_z)") end - r_global_grid = r_g - z_global_grid = z_g - - d_max_g = max(dR_ax, dZ_ax) - threshold_g = (10 * d_max_g)^2 * max(ψ_RR, ψ_ZZ) / (2 * psio_g) - psi_zoom_max = 9 * threshold_g - a_zoom_r = sqrt(2 * psi_zoom_max * psio_g / ψ_RR) * 1.2 - a_zoom_z = sqrt(2 * psi_zoom_max * psio_g / ψ_ZZ) * 1.2 - sinh_β = sinh(β_r_g) - nr_z = max(200, ceil(Int, 8 * β_r_g * a_zoom_r * 10 / (sinh_β * a_low_g))) - nz_z = max(200, ceil(Int, 8 * β_r_g * a_zoom_z * 10 / (sinh_β * a_low_g))) - r_zoom_grid_vis = Equilibrium.make_stretched_r_grid( - max(raw_inv.rmin, ro_g - a_zoom_r), min(raw_inv.rmax, ro_g + a_zoom_r), - ro_g, nr_z, β_r_g) - z_zoom_grid_vis = Equilibrium.make_stretched_r_grid( - max(raw_inv.zmin, zo_g - a_zoom_z), min(raw_inv.zmax, zo_g + a_zoom_z), - zo_g, nz_z, β_r_g) - println(" Grid vis: global $(nr_g)×$(nz_g), zoom $(nr_z)×$(nz_z)") -end end # haskey(pes, "efit_by_inversion") # ═══════════════════════════════════════════════════════════════════════════════ @@ -296,7 +300,7 @@ println("\n" * "=" ^ 70) println("2. Flux Surface Contour Overlays") println("=" ^ 70) -psi_contours = collect(range(psi_lo, psi_hi; length=20)) +psi_contours = collect(range(psi_lo, psi_hi; length=20)) theta_contour = range(0.0, 1.0; length=256) R_fs = Dict(m => flux_surface_RZ(pes[m], psi_contours, theta_contour) for m in all_methods) @@ -305,7 +309,7 @@ p_ctr_full = plot(; aspect_ratio=:equal, xlabel="R [m]", ylabel="Z [m]", title="Flux surfaces: all methods (psihigh=$psihigh_arg)") p_ctr_core = plot(; aspect_ratio=:equal, xlabel="R [m]", ylabel="Z [m]", title="Deep core zoom (innermost 4 surfaces)") -p_ctr_xpt = plot(; aspect_ratio=:equal, xlabel="R [m]", ylabel="Z [m]", +p_ctr_xpt = plot(; aspect_ratio=:equal, xlabel="R [m]", ylabel="Z [m]", title="Far edge / x-point zoom (outermost 3 surfaces)") for m in all_methods @@ -322,7 +326,7 @@ for m in all_methods ls=method_style[m], lw=1.5, label=lbl) end n_outer = length(psi_contours) - for k in (n_outer - 2):n_outer + for k in (n_outer-2):n_outer lbl = k == n_outer - 2 ? method_label[m] : "" plot!(p_ctr_xpt, Rs[k], Zs[k]; color=method_color[m], ls=method_style[m], lw=1.5, label=lbl) @@ -332,45 +336,47 @@ end # Grid overplots: scatter subsampled grid points on each panel (only if efit_by_inversion ran). # Global grid: every 20th R × 12th Z (grey). Zoom grid: every 3rd R × 3rd Z (darkgrey). if !isempty(r_global_grid) -let - step_rg, step_zg = 20, 12 - Rg = [r_global_grid[ir] for ir in 1:step_rg:length(r_global_grid) - for _ in 1:step_zg:length(z_global_grid)] - Zg = [z_global_grid[iz] for _ in 1:step_rg:length(r_global_grid) - for iz in 1:step_zg:length(z_global_grid)] - scatter!(p_ctr_full, Rg, Zg; ms=0.8, color=:grey, alpha=0.25, - markerstrokewidth=0, label="global grid") - - step_rz, step_zz = 3, 3 - Rz = [r_zoom_grid_vis[ir] for ir in 1:step_rz:length(r_zoom_grid_vis) - for _ in 1:step_zz:length(z_zoom_grid_vis)] - Zz = [z_zoom_grid_vis[iz] for _ in 1:step_rz:length(r_zoom_grid_vis) - for iz in 1:step_zz:length(z_zoom_grid_vis)] - scatter!(p_ctr_full, Rz, Zz; ms=0.8, color=:darkgrey, alpha=0.4, - markerstrokewidth=0, label="zoom grid") - - # Core panel: show both grids at full density within the core zoom region - scatter!(p_ctr_core, Rg, Zg; ms=1.2, color=:grey, alpha=0.3, - markerstrokewidth=0, label="global grid") - scatter!(p_ctr_core, Rz, Zz; ms=1.2, color=:darkgrey, alpha=0.5, - markerstrokewidth=0, label="zoom grid") - - # X-point panel: global grid only (zoom doesn't extend there) - scatter!(p_ctr_xpt, Rg, Zg; ms=1.2, color=:grey, alpha=0.3, - markerstrokewidth=0, label="global grid") -end + let + step_rg, step_zg = 20, 12 + Rg = [r_global_grid[ir] for ir in 1:step_rg:length(r_global_grid) + for _ in 1:step_zg:length(z_global_grid)] + Zg = [z_global_grid[iz] for _ in 1:step_rg:length(r_global_grid) + for iz in 1:step_zg:length(z_global_grid)] + scatter!(p_ctr_full, Rg, Zg; ms=0.8, color=:grey, alpha=0.25, + markerstrokewidth=0, label="global grid") + + step_rz, step_zz = 3, 3 + Rz = [r_zoom_grid_vis[ir] for ir in 1:step_rz:length(r_zoom_grid_vis) + for _ in 1:step_zz:length(z_zoom_grid_vis)] + Zz = [z_zoom_grid_vis[iz] for _ in 1:step_rz:length(r_zoom_grid_vis) + for iz in 1:step_zz:length(z_zoom_grid_vis)] + scatter!(p_ctr_full, Rz, Zz; ms=0.8, color=:darkgrey, alpha=0.4, + markerstrokewidth=0, label="zoom grid") + + # Core panel: show both grids at full density within the core zoom region + scatter!(p_ctr_core, Rg, Zg; ms=1.2, color=:grey, alpha=0.3, + markerstrokewidth=0, label="global grid") + scatter!(p_ctr_core, Rz, Zz; ms=1.2, color=:darkgrey, alpha=0.5, + markerstrokewidth=0, label="zoom grid") + + # X-point panel: global grid only (zoom doesn't extend there) + scatter!(p_ctr_xpt, Rg, Zg; ms=1.2, color=:grey, alpha=0.3, + markerstrokewidth=0, label="global grid") + end end # !isempty(r_global_grid) # Set zoom limits for core and x-point panels using the reference method Rc, Zc = R_fs[ref_method] n_core = 4 -all_R_c = vcat(Rc[1:n_core]...); all_Z_c = vcat(Zc[1:n_core]...) +all_R_c = vcat(Rc[1:n_core]...); +all_Z_c = vcat(Zc[1:n_core]...) pad = 0.03 xlims!(p_ctr_core, minimum(all_R_c) - pad, maximum(all_R_c) + pad) ylims!(p_ctr_core, minimum(all_Z_c) - pad, maximum(all_Z_c) + pad) n_outer = length(psi_contours) -all_R_e = vcat(Rc[(n_outer-2):n_outer]...); all_Z_e = vcat(Zc[(n_outer-2):n_outer]...) +all_R_e = vcat(Rc[(n_outer-2):n_outer]...); +all_Z_e = vcat(Zc[(n_outer-2):n_outer]...) xpt_idx = argmin(all_Z_e) xlims!(p_ctr_xpt, all_R_e[xpt_idx] - 0.20, all_R_e[xpt_idx] + 0.20) ylims!(p_ctr_xpt, all_Z_e[xpt_idx] - 0.05, all_Z_e[xpt_idx] + 0.40) @@ -388,7 +394,7 @@ p_tht_full = plot(; aspect_ratio=:equal, xlabel="R [m]", ylabel="Z [m]", title="θ = const lines: all methods (psihigh=$psihigh_arg)") p_tht_core = plot(; aspect_ratio=:equal, xlabel="R [m]", ylabel="Z [m]", title="Deep core zoom") -p_tht_xpt = plot(; aspect_ratio=:equal, xlabel="R [m]", ylabel="Z [m]", +p_tht_xpt = plot(; aspect_ratio=:equal, xlabel="R [m]", ylabel="Z [m]", title="Far edge / x-point zoom") for m in all_methods @@ -402,14 +408,14 @@ for m in all_methods Zs = [psi_theta_to_RZ(pe, ψ, θ)[2] for ψ in psi_dense] plot!(p_tht_full, Rs, Zs; color=method_color[m], ls=method_style[m], lw=0.9, alpha=0.7, label=lbl) plot!(p_tht_core, Rs, Zs; color=method_color[m], ls=method_style[m], lw=1.5, label=lbl) - plot!(p_tht_xpt, Rs, Zs; color=method_color[m], ls=method_style[m], lw=1.5, label=lbl) + plot!(p_tht_xpt, Rs, Zs; color=method_color[m], ls=method_style[m], lw=1.5, label=lbl) end # Grid dots at every (ψ_i, θ_j) intersection — by construction on the lines above Rg = [psi_theta_to_RZ(pe, ψ, θ)[1] for ψ in pe.rzphi_xs for θ in θ_sub] Zg = [psi_theta_to_RZ(pe, ψ, θ)[2] for ψ in pe.rzphi_xs for θ in θ_sub] scatter!(p_tht_full, Rg, Zg; ms=1.5, color=method_color[m], alpha=0.5, markerstrokewidth=0, label="") scatter!(p_tht_core, Rg, Zg; ms=2.0, color=method_color[m], alpha=0.6, markerstrokewidth=0, label="") - scatter!(p_tht_xpt, Rg, Zg; ms=2.0, color=method_color[m], alpha=0.6, markerstrokewidth=0, label="") + scatter!(p_tht_xpt, Rg, Zg; ms=2.0, color=method_color[m], alpha=0.6, markerstrokewidth=0, label="") end xlims!(p_tht_core, minimum(all_R_c) - pad, maximum(all_R_c) + pad) @@ -430,16 +436,16 @@ println("3. 2D rzphi Geometric Spline Profiles at Select θ Values") println("=" ^ 70) rzphi_specs = [ - ("r²=(R-R₀)²+(Z-Z₀)²", pe -> ((ψ, θ) -> pe.rzphi_rsquared((ψ, θ)))), + ("r²=(R-R₀)²+(Z-Z₀)²", pe -> ((ψ, θ) -> pe.rzphi_rsquared((ψ, θ)))), ("angle offset η/2π−θ", pe -> ((ψ, θ) -> pe.rzphi_offset((ψ, θ)))), - ("ν (toroidal shift)", pe -> ((ψ, θ) -> pe.rzphi_nu((ψ, θ)))), - ("Jacobian", pe -> ((ψ, θ) -> pe.rzphi_jac((ψ, θ)))), + ("ν (toroidal shift)", pe -> ((ψ, θ) -> pe.rzphi_nu((ψ, θ)))), + ("Jacobian", pe -> ((ψ, θ) -> pe.rzphi_jac((ψ, θ)))) ] rzphi_fnames = ["rzphi_rsquared", "rzphi_angle_offset", "rzphi_nu", "rzphi_jacobian"] for (sidx, (sname, fn_getter)) in enumerate(rzphi_specs) - fn_ref = fn_getter(pe_ref) - yd_all = [[fn_ref(ψ, θ) for ψ in psi_full] for θ in theta_select] + fn_ref = fn_getter(pe_ref) + yd_all = [[fn_ref(ψ, θ) for ψ in psi_full] for θ in theta_select] p_full = plot(; xlabel="ψ", ylabel=sname, legend=:best, xlims=(0, 1), title="$sname — full domain (psihigh=$psihigh_arg)") @@ -454,20 +460,25 @@ for (sidx, (sname, fn_getter)) in enumerate(rzphi_specs) plot!(p_full, psi_full, yd; color=tc, lw=2, label="efit θ=$(θ)") plot!(p_core, psi_full[mask_core], yd[mask_core]; color=tc, lw=2, label="efit θ=$(θ)") plot!(p_edge, t_edge_full, yd[mask_edge]; color=tc, lw=2, label="efit θ=$(θ)") - xs = pe_ref.rzphi_xs; ys = [fn_ref(ψ, θ) for ψ in xs] + xs = pe_ref.rzphi_xs + ys = [fn_ref(ψ, θ) for ψ in xs] scatter!(p_full, xs, ys; ms=3, markerstrokewidth=0, color=tc, label="") - let mask = xs .< 0.10; scatter!(p_core, xs[mask], ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") end - let mask = xs .> 0.98; scatter!(p_edge, -log.(1.0 .- xs[mask]), ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") end + let mask = xs .< 0.10 + scatter!(p_core, xs[mask], ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") + end + let mask = xs .> 0.98 + scatter!(p_edge, -log.(1.0 .- xs[mask]), ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") + end end println(" $sname:") for m in compare_methods_active - fn_m = fn_getter(pes[m]) + fn_m = fn_getter(pes[m]) yi_all = [[fn_m(ψ, θ) for ψ in psi_full] for θ in theta_select] for (tidx, θ) in enumerate(theta_select) tc = theta_colors[tidx] yi = yi_all[tidx] - Δ = yd_all[tidx] .- yi + Δ = yd_all[tidx] .- yi plot!(p_full, psi_full, yi; color=tc, lw=1.2, ls=method_style[m], label="$(method_label[m]) θ=$(θ)") plot!(p_core, psi_full[mask_core], yi[mask_core]; color=tc, lw=1.2, @@ -476,10 +487,15 @@ for (sidx, (sname, fn_getter)) in enumerate(rzphi_specs) ls=method_style[m], label="$(method_label[m]) θ=$(θ)") plot!(p_diff, psi_full, Δ; color=tc, lw=1.2, ls=method_style[m], label="(efit−$(method_label[m])) θ=$(θ)") - xs = pes[m].rzphi_xs; ys = [fn_m(ψ, θ) for ψ in xs] + xs = pes[m].rzphi_xs + ys = [fn_m(ψ, θ) for ψ in xs] scatter!(p_full, xs, ys; ms=3, markerstrokewidth=0, color=tc, label="") - let mask = xs .< 0.10; scatter!(p_core, xs[mask], ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") end - let mask = xs .> 0.98; scatter!(p_edge, -log.(1.0 .- xs[mask]), ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") end + let mask = xs .< 0.10 + scatter!(p_core, xs[mask], ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") + end + let mask = xs .> 0.98 + scatter!(p_edge, -log.(1.0 .- xs[mask]), ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") + end Δc = any(mask_core) ? Δ[mask_core] : [0.0] Δe = any(mask_edge) ? Δ[mask_edge] : [0.0] @@ -501,15 +517,15 @@ println("4. Physics (eqfun) Spline Profiles at Select θ Values") println("=" ^ 70) eqfun_specs = [ - ("|B| (total field [T])", pe -> ((ψ, θ) -> pe.eqfun_B((ψ, θ)))), + ("|B| (total field [T])", pe -> ((ψ, θ) -> pe.eqfun_B((ψ, θ)))), ("metric1 (e₁·e₂+q·e₃·e₁)/JB²", pe -> ((ψ, θ) -> pe.eqfun_metric1((ψ, θ)))), - ("metric2 (e₂·e₃+q·e₃²)/JB²", pe -> ((ψ, θ) -> pe.eqfun_metric2((ψ, θ)))), + ("metric2 (e₂·e₃+q·e₃²)/JB²", pe -> ((ψ, θ) -> pe.eqfun_metric2((ψ, θ)))) ] eqfun_fnames = ["eqfun_Bmag", "eqfun_metric1", "eqfun_metric2"] for (eidx, (ename, fn_getter)) in enumerate(eqfun_specs) - fn_ref = fn_getter(pe_ref) - yd_all = [[fn_ref(ψ, θ) for ψ in psi_full] for θ in theta_select] + fn_ref = fn_getter(pe_ref) + yd_all = [[fn_ref(ψ, θ) for ψ in psi_full] for θ in theta_select] p_full = plot(; xlabel="ψ", ylabel=ename, legend=:best, xlims=(0, 1), title="$ename — full domain (psihigh=$psihigh_arg)") @@ -524,20 +540,25 @@ for (eidx, (ename, fn_getter)) in enumerate(eqfun_specs) plot!(p_full, psi_full, yd; color=tc, lw=2, label="efit θ=$(θ)") plot!(p_core, psi_full[mask_core], yd[mask_core]; color=tc, lw=2, label="efit θ=$(θ)") plot!(p_edge, t_edge_full, yd[mask_edge]; color=tc, lw=2, label="efit θ=$(θ)") - xs = pe_ref.rzphi_xs; ys = [fn_ref(ψ, θ) for ψ in xs] + xs = pe_ref.rzphi_xs + ys = [fn_ref(ψ, θ) for ψ in xs] scatter!(p_full, xs, ys; ms=3, markerstrokewidth=0, color=tc, label="") - let mask = xs .< 0.10; scatter!(p_core, xs[mask], ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") end - let mask = xs .> 0.98; scatter!(p_edge, -log.(1.0 .- xs[mask]), ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") end + let mask = xs .< 0.10 + scatter!(p_core, xs[mask], ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") + end + let mask = xs .> 0.98 + scatter!(p_edge, -log.(1.0 .- xs[mask]), ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") + end end println(" $ename:") for m in compare_methods_active - fn_m = fn_getter(pes[m]) + fn_m = fn_getter(pes[m]) yi_all = [[fn_m(ψ, θ) for ψ in psi_full] for θ in theta_select] for (tidx, θ) in enumerate(theta_select) tc = theta_colors[tidx] yi = yi_all[tidx] - Δ = yd_all[tidx] .- yi + Δ = yd_all[tidx] .- yi plot!(p_full, psi_full, yi; color=tc, lw=1.2, ls=method_style[m], label="$(method_label[m]) θ=$(θ)") plot!(p_core, psi_full[mask_core], yi[mask_core]; color=tc, lw=1.2, @@ -546,10 +567,15 @@ for (eidx, (ename, fn_getter)) in enumerate(eqfun_specs) ls=method_style[m], label="$(method_label[m]) θ=$(θ)") plot!(p_diff, psi_full, Δ; color=tc, lw=1.2, ls=method_style[m], label="(efit−$(method_label[m])) θ=$(θ)") - xs = pes[m].rzphi_xs; ys = [fn_m(ψ, θ) for ψ in xs] + xs = pes[m].rzphi_xs + ys = [fn_m(ψ, θ) for ψ in xs] scatter!(p_full, xs, ys; ms=3, markerstrokewidth=0, color=tc, label="") - let mask = xs .< 0.10; scatter!(p_core, xs[mask], ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") end - let mask = xs .> 0.98; scatter!(p_edge, -log.(1.0 .- xs[mask]), ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") end + let mask = xs .< 0.10 + scatter!(p_core, xs[mask], ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") + end + let mask = xs .> 0.98 + scatter!(p_edge, -log.(1.0 .- xs[mask]), ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") + end Δc = any(mask_core) ? Δ[mask_core] : [0.0] Δe = any(mask_edge) ? Δ[mask_edge] : [0.0] @@ -580,13 +606,13 @@ function row_int(label, vals) @printf(" %-22s %s\n", label, join([@sprintf("%18d", v) for v in vals])) end -row("ro [m]", [pes[m].ro for m in all_methods]) -row("zo [m]", [pes[m].zo for m in all_methods]) -row("psio [Wb/rad]",[pes[m].psio for m in all_methods]) -row("psilow", [pes[m].rzphi_xs[1] for m in all_methods]) -row("psihigh", [pes[m].rzphi_xs[end] for m in all_methods]) -row("q(psilow)", [pes[m].profiles.q_spline(pes[m].rzphi_xs[1]) for m in all_methods]) -row("q(psihigh)", [pes[m].profiles.q_spline(pes[m].rzphi_xs[end]) for m in all_methods]) +row("ro [m]", [pes[m].ro for m in all_methods]) +row("zo [m]", [pes[m].zo for m in all_methods]) +row("psio [Wb/rad]", [pes[m].psio for m in all_methods]) +row("psilow", [pes[m].rzphi_xs[1] for m in all_methods]) +row("psihigh", [pes[m].rzphi_xs[end] for m in all_methods]) +row("q(psilow)", [pes[m].profiles.q_spline(pes[m].rzphi_xs[1]) for m in all_methods]) +row("q(psihigh)", [pes[m].profiles.q_spline(pes[m].rzphi_xs[end]) for m in all_methods]) q_profiles = Dict(m => [pes[m].profiles.q_spline(ψ) for ψ in psi_full] for m in all_methods) row_int("q non-mono (edge)", diff --git a/benchmarks/plot_xi_eigenmode.jl b/benchmarks/plot_xi_eigenmode.jl index 78e26ee82..1d35a834e 100644 --- a/benchmarks/plot_xi_eigenmode.jl +++ b/benchmarks/plot_xi_eigenmode.jl @@ -39,7 +39,7 @@ for ip in 1:nstep @views mul!(xi[:, ip], u1[:, :, ip], c) end -ms = mlow .+ (0:mpert-1) +ms = mlow .+ (0:(mpert-1)) peak = [maximum(abs, @view xi[i, :]) for i in 1:mpert] order = sortperm(peak; rev=true) # dominant harmonics first diff --git a/benchmarks/verify_gal_match.jl b/benchmarks/verify_gal_match.jl index 51dcdd868..28ad6f2c0 100644 --- a/benchmarks/verify_gal_match.jl +++ b/benchmarks/verify_gal_match.jl @@ -19,7 +19,12 @@ xi, dxi, cout, cin, deltar, eig, resid, sing_psi = h5open(h5path) do f end # HDF5 stores ComplexF64 as a compound (re,im); convert if needed to_c(a) = eltype(a) <: Complex ? a : map(x -> ComplexF64(x.re, x.im), a) -xi = to_c(xi); dxi = to_c(dxi); cout = to_c(cout); cin = to_c(cin); deltar = to_c(deltar); eig = to_c(eig) +xi = to_c(xi); +dxi = to_c(dxi); +cout = to_c(cout); +cin = to_c(cin); +deltar = to_c(deltar); +eig = to_c(eig) mpert, mcoil, ngrid = size(xi) msing = size(deltar, 1) diff --git a/docs/make.jl b/docs/make.jl index 92b605efc..2a971d4a4 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -40,9 +40,9 @@ makedocs(; "Tearing" => "inner_layer.md", "Analysis" => "analysis.md", "Utilities" => "utilities.md" - ], + ], "Citations" => "citations.md", - "Developer Notes" => "developer_notes.md", + "Developer Notes" => "developer_notes.md" ], checkdocs=:exports ) diff --git a/docs/src/forcing_terms.md b/docs/src/forcing_terms.md index ba2f7d752..e88c11596 100644 --- a/docs/src/forcing_terms.md +++ b/docs/src/forcing_terms.md @@ -60,7 +60,7 @@ amplitudes directly — no conversion is applied. Required datasets: - `n`: integer array of toroidal mode numbers -- `m`: integer array of poloidal mode numbers +- `m`: integer array of poloidal mode numbers - `amplitude_real`: float array of real parts - `amplitude_imag`: float array of imaginary parts (optional) diff --git a/examples/DIIID-like_SLAYER_example/gpec.toml b/examples/DIIID-like_SLAYER_example/gpec.toml index 487d41f9b..d5dfe09c3 100644 --- a/examples/DIIID-like_SLAYER_example/gpec.toml +++ b/examples/DIIID-like_SLAYER_example/gpec.toml @@ -86,3 +86,12 @@ Q_re_range = [-2.0, 2.0] # Scan box in the normalized Q plane, Re(Q) axis Q_im_range = [-0.5, 3.0] # Scan box in the normalized Q plane, Im(Q) axis nre = 41 # Grid resolution along the Re(Q) axis nim = 31 # Grid resolution along the Im(Q) axis + +[CriticalResonantField] +# CriticalResonantField used to find the critical resonant field sufficent for tearing onset at each rational surface. +enabled = true # Run CriticalResonantField analysis +inner_model = "slayer_fitzpatrick" # Inner-layer Δ(Q) model: "slayer_fitzpatrick", "ggj_shooting", or "ggj_galerkin" +Qmin = -10 # Minimum rotation scanned +Qmax = 10 # Maximum rotation scanned +n = 200 # Number of rotation points scanned +profile_file = "../DIIID-like_ideal_example/TkMkr_D3Dlike_Hmode_kinetic.h5" # Kinetic-profile file (relative to the run dir), required when SLAYER is enabled diff --git a/examples/DIIID-like_ideal_example/analyze_example.jl b/examples/DIIID-like_ideal_example/analyze_example.jl index 715e3ec76..dae831848 100644 --- a/examples/DIIID-like_ideal_example/analyze_example.jl +++ b/examples/DIIID-like_ideal_example/analyze_example.jl @@ -41,7 +41,7 @@ function symmetric_clims(z) end geqdsk_cases = [ - "TkMkr_D3Dlike_Hmode.geqdsk", + "TkMkr_D3Dlike_Hmode.geqdsk" ] base_toml = TOML.parsefile(joinpath(@__DIR__, "gpec.toml")) diff --git a/examples/DIIID-like_ideal_example_IMAS/run_imas_example.jl b/examples/DIIID-like_ideal_example_IMAS/run_imas_example.jl index c4fe1637f..0e416e317 100644 --- a/examples/DIIID-like_ideal_example_IMAS/run_imas_example.jl +++ b/examples/DIIID-like_ideal_example_IMAS/run_imas_example.jl @@ -57,8 +57,8 @@ try config_imas = merge(SHARED_CONFIG, Dict("Equilibrium" => merge(EQ_COMMON, Dict("eq_type" => "imas", "eq_filename" => "from_dd", "imas_cocos" => 11)))) open(joinpath(tmpdir_imas, "gpec.toml"), "w") do io - ; - TOML.print(io, config_imas); + + TOML.print(io, config_imas) end result_imas = GPEC.main([tmpdir_imas]; dd=dd) global et_imas = real(result_imas.ffs.free_boundary.et[1]) @@ -76,8 +76,8 @@ try config_gfile = merge(SHARED_CONFIG, Dict("Equilibrium" => merge(EQ_COMMON, Dict("eq_type" => "efit", "eq_filename" => GEQDSK)))) open(joinpath(tmpdir_gfile, "gpec.toml"), "w") do io - ; - TOML.print(io, config_gfile); + + TOML.print(io, config_gfile) end result_gfile = GPEC.main([tmpdir_gfile]) global et_gfile = real(result_gfile.ffs.free_boundary.et[1]) diff --git a/examples/LAR_beta_scan/run_scan.jl b/examples/LAR_beta_scan/run_scan.jl index 6249ff30d..f6105a2ae 100644 --- a/examples/LAR_beta_scan/run_scan.jl +++ b/examples/LAR_beta_scan/run_scan.jl @@ -30,11 +30,11 @@ using Printf # is approximately uniform over most of the range and smoothly tightens as # the pole is approached, giving an even visual cadence without wasting # points on the flat-slope region far from the pole. -function _warped_grid(x_start::Float64, x_end::Float64, N::Int; p::Float64 = 2.0) - return [x_start + (x_end - x_start) * (1 - (1 - i / (N - 1))^p) for i in 0:N-1] +function _warped_grid(x_start::Float64, x_end::Float64, N::Int; p::Float64=2.0) + return [x_start + (x_end - x_start) * (1 - (1 - i / (N - 1))^p) for i in 0:(N-1)] end -const PC_FULL = _warped_grid(0.001, 0.1735, 40; p = 2.0) +const PC_FULL = _warped_grid(0.001, 0.1735, 40; p=2.0) const PC_TEST = [0.001, 0.10, 0.17] @@ -58,7 +58,9 @@ function run_single(pc::Float64) config = deepcopy(GPEC_BASE) config["TJ_ANALYTIC_INPUT"]["pc"] = pc config["ForceFreeStates"]["HDF5_filename"] = joinpath(run_dir, "gpec.h5") - open(joinpath(run_dir, "gpec.toml"), "w") do io; TOML.print(io, config); end + open(joinpath(run_dir, "gpec.toml"), "w") do io + TOML.print(io, config) + end GeneralizedPerturbedEquilibrium.main([run_dir]) return extract_results(joinpath(run_dir, "gpec.h5")) @@ -73,24 +75,32 @@ end function extract_results(h5_path::String) h5open(h5_path, "r") do f fbs = "ForceFreeStates/FreeBoundaryStability" - ep = read(f, "$fbs/eigenmode_plasma_energies"); ev = read(f, "$fbs/eigenmode_vacuum_energies"); et = read(f, "$fbs/eigenmode_energies") + ep = read(f, "$fbs/eigenmode_plasma_energies") + ev = read(f, "$fbs/eigenmode_vacuum_energies") + et = read(f, "$fbs/eigenmode_energies") msing = read(f, "SingularSurfaces/rational_count") m_sing = read(f, "SingularSurfaces/rational_m") dp_mat = haskey(f, "SingularSurfaces/Delta_prime_matrix") ? read(f, "SingularSurfaces/Delta_prime_matrix") : nothing qlim = haskey(f, "Info/qlim") ? read(f, "Info/qlim") : read(f, "Equilibrium/q_max") - q0 = read(f, "Equilibrium/q_axis"); qmax = read(f, "Equilibrium/q_max") + q0 = read(f, "Equilibrium/q_axis") + qmax = read(f, "Equilibrium/q_max") - dp_21 = NaN + NaN*im; dp_31 = NaN + NaN*im + dp_21 = NaN + NaN*im + dp_31 = NaN + NaN*im if dp_mat !== nothing && msing > 0 for s in 1:min(msing, size(dp_mat, 1)) m_val = size(m_sing, 1) == msing ? m_sing[s, 1] : m_sing[1, s] - if m_val == 2; dp_21 = dp_mat[s, s]; end - if m_val == 3; dp_31 = dp_mat[s, s]; end + if m_val == 2 + dp_21 = dp_mat[s, s] + end + if m_val == 3 + dp_31 = dp_mat[s, s] + end end end return (dp_21=dp_21, dp_31=dp_31, - dW_plasma=real(ep[1]), dW_vacuum=real(ev[1]), dW_total=real(et[1]), - q0=q0, qmax=qmax, qlim=qlim, msing=msing, dp_matrix=dp_mat) + dW_plasma=real(ep[1]), dW_vacuum=real(ev[1]), dW_total=real(et[1]), + q0=q0, qmax=qmax, qlim=qlim, msing=msing, dp_matrix=dp_mat) end end @@ -117,11 +127,20 @@ function main() haskey(f, gname) && delete_object(f, gname) g = create_group(f, gname) g["pressure_factor"] = pc - g["dp_21_real"] = real(result.dp_21); g["dp_21_imag"] = imag(result.dp_21) - g["dp_31_real"] = real(result.dp_31); g["dp_31_imag"] = imag(result.dp_31) - g["dW_plasma"] = result.dW_plasma; g["dW_vacuum"] = result.dW_vacuum; g["dW_total"] = result.dW_total - g["q0"] = result.q0; g["qmax"] = result.qmax; g["qlim"] = result.qlim; g["msing"] = result.msing - if result.dp_matrix !== nothing; g["dp_matrix"] = result.dp_matrix; end + g["dp_21_real"] = real(result.dp_21) + g["dp_21_imag"] = imag(result.dp_21) + g["dp_31_real"] = real(result.dp_31) + g["dp_31_imag"] = imag(result.dp_31) + g["dW_plasma"] = result.dW_plasma + g["dW_vacuum"] = result.dW_vacuum + g["dW_total"] = result.dW_total + g["q0"] = result.q0 + g["qmax"] = result.qmax + g["qlim"] = result.qlim + g["msing"] = result.msing + if result.dp_matrix !== nothing + g["dp_matrix"] = result.dp_matrix + end end @printf(" dp21=%+.4f%+.4fi dp31=%+.4f%+.4fi dW_t=%+.6f qa=%.3f\n", real(result.dp_21), imag(result.dp_21), real(result.dp_31), imag(result.dp_31), diff --git a/examples/LAR_epsilon_scan/run_scan.jl b/examples/LAR_epsilon_scan/run_scan.jl index e3327ab95..f487332f0 100644 --- a/examples/LAR_epsilon_scan/run_scan.jl +++ b/examples/LAR_epsilon_scan/run_scan.jl @@ -30,11 +30,11 @@ using Printf # spacing tightens smoothly as the pole is approached — the flat low-ε # region is covered with even cadence, and more points land in the final # few percent where Δ' rises by orders of magnitude. -function _warped_grid(x_start::Float64, x_end::Float64, N::Int; p::Float64 = 2.0) - return [x_start + (x_end - x_start) * (1 - (1 - i / (N - 1))^p) for i in 0:N-1] +function _warped_grid(x_start::Float64, x_end::Float64, N::Int; p::Float64=2.0) + return [x_start + (x_end - x_start) * (1 - (1 - i / (N - 1))^p) for i in 0:(N-1)] end -const EPSILONS_FULL = _warped_grid(0.125, 0.660, 56; p = 2.0) +const EPSILONS_FULL = _warped_grid(0.125, 0.660, 56; p=2.0) const EPSILONS_TEST = [0.2495, 0.4072, 0.5510] @@ -65,7 +65,9 @@ function run_single(epsilon::Float64) config["TJ_ANALYTIC_INPUT"]["lar_r0"] = GPEC_BASE["TJ_ANALYTIC_INPUT"]["lar_a"] / epsilon config["Equilibrium"]["eq_type"] = "tj_analytic_direct" config["ForceFreeStates"]["HDF5_filename"] = joinpath(run_dir, "gpec.h5") - open(joinpath(run_dir, "gpec.toml"), "w") do io; TOML.print(io, config); end + open(joinpath(run_dir, "gpec.toml"), "w") do io + TOML.print(io, config) + end GeneralizedPerturbedEquilibrium.main([run_dir]) return extract_results(joinpath(run_dir, "gpec.h5")) @@ -80,24 +82,32 @@ end function extract_results(h5_path::String) h5open(h5_path, "r") do f fbs = "ForceFreeStates/FreeBoundaryStability" - ep = read(f, "$fbs/eigenmode_plasma_energies"); ev = read(f, "$fbs/eigenmode_vacuum_energies"); et = read(f, "$fbs/eigenmode_energies") + ep = read(f, "$fbs/eigenmode_plasma_energies") + ev = read(f, "$fbs/eigenmode_vacuum_energies") + et = read(f, "$fbs/eigenmode_energies") msing = read(f, "SingularSurfaces/rational_count") m_sing = read(f, "SingularSurfaces/rational_m") dp_mat = haskey(f, "SingularSurfaces/Delta_prime_matrix") ? read(f, "SingularSurfaces/Delta_prime_matrix") : nothing qlim = haskey(f, "Info/qlim") ? read(f, "Info/qlim") : read(f, "Equilibrium/q_max") - q0 = read(f, "Equilibrium/q_axis"); qmax = read(f, "Equilibrium/q_max") + q0 = read(f, "Equilibrium/q_axis") + qmax = read(f, "Equilibrium/q_max") - dp_21 = NaN + NaN*im; dp_31 = NaN + NaN*im + dp_21 = NaN + NaN*im + dp_31 = NaN + NaN*im if dp_mat !== nothing && msing > 0 for s in 1:min(msing, size(dp_mat, 1)) m_val = size(m_sing, 1) == msing ? m_sing[s, 1] : m_sing[1, s] - if m_val == 2; dp_21 = dp_mat[s, s]; end - if m_val == 3; dp_31 = dp_mat[s, s]; end + if m_val == 2 + dp_21 = dp_mat[s, s] + end + if m_val == 3 + dp_31 = dp_mat[s, s] + end end end return (dp_21=dp_21, dp_31=dp_31, - dW_plasma=real(ep[1]), dW_vacuum=real(ev[1]), dW_total=real(et[1]), - q0=q0, qmax=qmax, qlim=qlim, msing=msing, dp_matrix=dp_mat) + dW_plasma=real(ep[1]), dW_vacuum=real(ev[1]), dW_total=real(et[1]), + q0=q0, qmax=qmax, qlim=qlim, msing=msing, dp_matrix=dp_mat) end end @@ -125,11 +135,20 @@ function main() haskey(f, gname) && delete_object(f, gname) g = create_group(f, gname) g["epsilon"] = eps - g["dp_21_real"] = real(result.dp_21); g["dp_21_imag"] = imag(result.dp_21) - g["dp_31_real"] = real(result.dp_31); g["dp_31_imag"] = imag(result.dp_31) - g["dW_plasma"] = result.dW_plasma; g["dW_vacuum"] = result.dW_vacuum; g["dW_total"] = result.dW_total - g["q0"] = result.q0; g["qmax"] = result.qmax; g["qlim"] = result.qlim; g["msing"] = result.msing - if result.dp_matrix !== nothing; g["dp_matrix"] = result.dp_matrix; end + g["dp_21_real"] = real(result.dp_21) + g["dp_21_imag"] = imag(result.dp_21) + g["dp_31_real"] = real(result.dp_31) + g["dp_31_imag"] = imag(result.dp_31) + g["dW_plasma"] = result.dW_plasma + g["dW_vacuum"] = result.dW_vacuum + g["dW_total"] = result.dW_total + g["q0"] = result.q0 + g["qmax"] = result.qmax + g["qlim"] = result.qlim + g["msing"] = result.msing + if result.dp_matrix !== nothing + g["dp_matrix"] = result.dp_matrix + end end @printf(" dp21=%+.4f%+.4fi dp31=%+.4f%+.4fi dW_t=%+.6f qa=%.3f\n", real(result.dp_21), imag(result.dp_21), real(result.dp_31), imag(result.dp_31), diff --git a/examples/Solovev_ideal_example/analyze_example.jl b/examples/Solovev_ideal_example/analyze_example.jl index 4c5a8eb7c..f3d6f0b99 100644 --- a/examples/Solovev_ideal_example/analyze_example.jl +++ b/examples/Solovev_ideal_example/analyze_example.jl @@ -9,8 +9,11 @@ h5path = joinpath(@__DIR__, "gpec.h5") # Summary plots p_eq = Analysis.Equilibrium.plot_equilibrium_summary(h5path) p_ffs = Analysis.ForceFreeStates.plot_ffs_summary(h5path) -p_pe = Analysis.PerturbedEquilibrium.plot_perturbed_equilibrium_summary(h5path) +p_pe = Analysis.PerturbedEquilibrium.plot_perturbed_equilibrium_summary(h5path) -display(p_eq); Plots.savefig(p_eq, joinpath(@__DIR__, "equilibrium_summary.png")) -display(p_ffs); Plots.savefig(p_ffs, joinpath(@__DIR__, "ffs_summary.png")) -display(p_pe); Plots.savefig(p_pe, joinpath(@__DIR__, "pe_summary.png")) \ No newline at end of file +display(p_eq); +Plots.savefig(p_eq, joinpath(@__DIR__, "equilibrium_summary.png")) +display(p_ffs); +Plots.savefig(p_ffs, joinpath(@__DIR__, "ffs_summary.png")) +display(p_pe); +Plots.savefig(p_pe, joinpath(@__DIR__, "pe_summary.png")) diff --git a/examples/Solovev_ideal_example_multi_n/analyze_example.jl b/examples/Solovev_ideal_example_multi_n/analyze_example.jl index 3a1e46134..068dd2a0d 100644 --- a/examples/Solovev_ideal_example_multi_n/analyze_example.jl +++ b/examples/Solovev_ideal_example_multi_n/analyze_example.jl @@ -9,11 +9,14 @@ h5path = joinpath(@__DIR__, "gpec.h5") # Summary plots p_eq = Analysis.Equilibrium.plot_equilibrium_summary(h5path) p_ffs = Analysis.ForceFreeStates.plot_ffs_summary(h5path) -p_pe = Analysis.PerturbedEquilibrium.plot_perturbed_equilibrium_summary(h5path) +p_pe = Analysis.PerturbedEquilibrium.plot_perturbed_equilibrium_summary(h5path) -display(p_eq); Plots.savefig(p_eq, joinpath(@__DIR__, "equilibrium_summary.png")) -display(p_ffs); Plots.savefig(p_ffs, joinpath(@__DIR__, "ffs_summary.png")) -display(p_pe); Plots.savefig(p_pe, joinpath(@__DIR__, "pe_summary.png")) +display(p_eq); +Plots.savefig(p_eq, joinpath(@__DIR__, "equilibrium_summary.png")) +display(p_ffs); +Plots.savefig(p_ffs, joinpath(@__DIR__, "ffs_summary.png")) +display(p_pe); +Plots.savefig(p_pe, joinpath(@__DIR__, "pe_summary.png")) # Analyze the single-n runs h5path_n1 = joinpath(@__DIR__, "single_n_1", "euler_n1.h5") @@ -21,5 +24,7 @@ h5path_n2 = joinpath(@__DIR__, "single_n_2", "euler_n2.h5") p_n1 = Analysis.ForceFreeStates.plot_ffs_summary(h5path_n1) p_n2 = Analysis.ForceFreeStates.plot_ffs_summary(h5path_n2) -display(p_n1); Plots.savefig(p_n1, joinpath(@__DIR__, "single_n_1", "ffs_summary.png")) -display(p_n2); Plots.savefig(p_n2, joinpath(@__DIR__, "single_n_2", "ffs_summary.png")) +display(p_n1); +Plots.savefig(p_n1, joinpath(@__DIR__, "single_n_1", "ffs_summary.png")) +display(p_n2); +Plots.savefig(p_n2, joinpath(@__DIR__, "single_n_2", "ffs_summary.png")) diff --git a/regression-harness/src/database.jl b/regression-harness/src/database.jl index c9a06b303..c7f043bc2 100644 --- a/regression-harness/src/database.jl +++ b/regression-harness/src/database.jl @@ -50,7 +50,9 @@ added by a later schema migration (NULL on every pre-existing row) need both cas """ _column(x, default) = (x === nothing || x === missing) ? default : x -"""Materialize SQLite query results as a Vector of NamedTuples.""" +""" +Materialize SQLite query results as a Vector of NamedTuples. +""" function query_rows(db::SQLite.DB, sql::String, params=()) result = DBInterface.execute(db, sql, params) ct = Tables.columntable(result) @@ -70,7 +72,9 @@ const ENV_COLUMNS = [ ("pinned", "INTEGER") ] -"""Add any `runs` columns missing from a database created by an earlier harness version.""" +""" +Add any `runs` columns missing from a database created by an earlier harness version. +""" function migrate_schema!(db::SQLite.DB) existing = Set(String[]) for row in query_rows(db, "PRAGMA table_info(runs)") @@ -107,10 +111,10 @@ environment. Rows predating fingerprinting hold NULL and therefore never match entries most likely to be misleading are exactly the ones that get re-run. """ function is_cached(db::SQLite.DB, commit_hash::String, case_name::String; - expected_key::Union{String,Nothing}=nothing)::Bool + expected_key::Union{String,Nothing}=nothing)::Bool if expected_key === nothing rows = query_rows(db, "SELECT id FROM runs WHERE commit_hash = ? AND case_name = ? AND success = 1", - (commit_hash, case_name)) + (commit_hash, case_name)) return !isempty(rows) end rows = query_rows(db, @@ -125,7 +129,7 @@ fingerprinting. Used to explain *why* a cached result was rejected. """ function cached_env_key(db::SQLite.DB, commit_hash::String, case_name::String)::Union{String,Nothing} rows = query_rows(db, "SELECT env_key FROM runs WHERE commit_hash = ? AND case_name = ?", - (commit_hash, case_name)) + (commit_hash, case_name)) isempty(rows) && return nothing key = _column(first(rows).env_key, nothing) key === nothing && return nothing @@ -135,15 +139,15 @@ end function delete_cached(db::SQLite.DB, commit_hash::String, case_name::String) # ON DELETE CASCADE handles quantities cleanup automatically DBInterface.execute(db, "DELETE FROM runs WHERE commit_hash = ? AND case_name = ?", - (commit_hash, case_name)) + (commit_hash, case_name)) end function store_run(db::SQLite.DB, commit_hash::AbstractString, commit_short::AbstractString, - commit_date::AbstractString, commit_msg::AbstractString, - case_name::AbstractString, runtime_s::Float64, - extracted::Vector{ExtractedQuantity}; - success::Bool=true, error_msg::AbstractString="", - fingerprint::EnvFingerprint=UNKNOWN_ENV) + commit_date::AbstractString, commit_msg::AbstractString, + case_name::AbstractString, runtime_s::Float64, + extracted::Vector{ExtractedQuantity}; + success::Bool=true, error_msg::AbstractString="", + fingerprint::EnvFingerprint=UNKNOWN_ENV) ran_at = Dates.format(Dates.now(), "yyyy-mm-ddTHH:MM:SS") SQLite.transaction(db) do @@ -155,10 +159,10 @@ function store_run(db::SQLite.DB, commit_hash::AbstractString, commit_short::Abs env_key, julia_version, os_arch, manifest_sha, nthreads, blas_threads, pinned) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""", (String(commit_hash), String(commit_short), String(commit_date), String(commit_msg), - String(case_name), ran_at, runtime_s, success ? 1 : 0, String(error_msg), - env_key(fingerprint), fingerprint.julia_version, fingerprint.os_arch, - fingerprint.manifest_sha, fingerprint.nthreads, fingerprint.blas_threads, - fingerprint.pinned ? 1 : 0)) + String(case_name), ran_at, runtime_s, success ? 1 : 0, String(error_msg), + env_key(fingerprint), fingerprint.julia_version, fingerprint.os_arch, + fingerprint.manifest_sha, fingerprint.nthreads, fingerprint.blas_threads, + fingerprint.pinned ? 1 : 0)) run_id = SQLite.last_insert_rowid(db) @@ -168,14 +172,14 @@ function store_run(db::SQLite.DB, commit_hash::AbstractString, commit_short::Abs (run_id, qty_name, qty_label, value_real, value_int, value_text, value_type, noise_threshold) VALUES (?, ?, ?, ?, ?, ?, ?, ?)""", (run_id, eq.name, eq.label, eq.value_real, eq.value_int, eq.value_text, - eq.value_type, eq.noise_threshold)) + eq.value_type, eq.noise_threshold)) end end end function store_failed_run(db::SQLite.DB, commit_hash::AbstractString, commit_short::AbstractString, - commit_date::AbstractString, commit_msg::AbstractString, - case_name::AbstractString, error_msg::AbstractString) + commit_date::AbstractString, commit_msg::AbstractString, + case_name::AbstractString, error_msg::AbstractString) ran_at = Dates.format(Dates.now(), "yyyy-mm-ddTHH:MM:SS") delete_cached(db, String(commit_hash), String(case_name)) DBInterface.execute(db, @@ -183,14 +187,14 @@ function store_failed_run(db::SQLite.DB, commit_hash::AbstractString, commit_sho (commit_hash, commit_short, commit_date, commit_msg, case_name, ran_at, runtime_s, success, error_msg) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""", (String(commit_hash), String(commit_short), String(commit_date), String(commit_msg), - String(case_name), ran_at, 0.0, 0, String(error_msg))) + String(case_name), ran_at, 0.0, 0, String(error_msg))) end """ Get all quantities for a (commit, case) pair. Returns Dict{qty_name => NamedTuple}. """ function get_quantities(db::SQLite.DB, commit_hash::String, case_name::String) - results = Dict{String, NamedTuple}() + results = Dict{String,NamedTuple}() rows = query_rows(db, """SELECT q.qty_name, q.qty_label, q.value_real, q.value_int, q.value_text, q.value_type, q.noise_threshold @@ -202,12 +206,12 @@ function get_quantities(db::SQLite.DB, commit_hash::String, case_name::String) for row in rows name = something(row.qty_name, "") results[name] = ( - label = something(row.qty_label, name), - value_real = row.value_real, - value_int = row.value_int, - value_text = row.value_text, - value_type = something(row.value_type, "missing"), - noise_threshold = something(row.noise_threshold, 0.0), + label=something(row.qty_label, name), + value_real=row.value_real, + value_int=row.value_int, + value_text=row.value_text, + value_type=something(row.value_type, "missing"), + noise_threshold=something(row.noise_threshold, 0.0) ) end return results @@ -233,13 +237,13 @@ function get_run_info(db::SQLite.DB, commit_hash::String, case_name::String) _column(row.pinned, 0) == 1 ) return ( - commit_short = something(row.commit_short, ""), - commit_date = something(row.commit_date, ""), - commit_msg = something(row.commit_msg, ""), - runtime_s = something(row.runtime_s, 0.0), - success = coalesce(row.success, 0) == 1, - error_msg = something(row.error_msg, ""), - fingerprint = fingerprint, + commit_short=something(row.commit_short, ""), + commit_date=something(row.commit_date, ""), + commit_msg=something(row.commit_msg, ""), + runtime_s=something(row.runtime_s, 0.0), + success=coalesce(row.success, 0) == 1, + error_msg=something(row.error_msg, ""), + fingerprint=fingerprint ) end diff --git a/regression-harness/src/env.jl b/regression-harness/src/env.jl index 20718c4cb..a7db6d339 100644 --- a/regression-harness/src/env.jl +++ b/regression-harness/src/env.jl @@ -49,7 +49,9 @@ end env_key(fp::EnvFingerprint) = env_key(fp.julia_version, fp.os_arch, fp.pinned ? fp.manifest_sha : "unpinned") -"""SHA-256 of a file, or "" when it does not exist.""" +""" +SHA-256 of a file, or "" when it does not exist. +""" function file_sha256(path::AbstractString)::String isfile(path) || return "" return bytes2hex(SHA.sha256(read(path))) @@ -108,7 +110,9 @@ function read_runinfo(path::String, pinned::Bool) return (something(runtime_s, NaN), fp) end -"""One-line human-readable summary of an environment, for report headers.""" +""" +One-line human-readable summary of an environment, for report headers. +""" function describe_env(fp::EnvFingerprint)::String isempty(fp.julia_version) && return "environment unknown (cached before fingerprinting)" mani = isempty(fp.manifest_sha) ? "no Manifest" : "manifest " * fp.manifest_sha[1:min(8, end)] diff --git a/regression-harness/src/reporter.jl b/regression-harness/src/reporter.jl index 4fdecfbe3..2fef2b990 100644 --- a/regression-harness/src/reporter.jl +++ b/regression-harness/src/reporter.jl @@ -233,7 +233,7 @@ function report_two_ref_comparison(db::SQLite.DB, case_spec::CaseSpec, println("Summary: ", join(parts, ", ")) println() return (n_ok=n_ok, n_changed=n_changed, n_missing=n_missing, - n_failed=count(identity, (failed1, failed2))) + n_failed=count(identity, (failed1, failed2))) end """ @@ -366,7 +366,7 @@ function report_multi_ref(db::SQLite.DB, case_spec::CaseSpec, end end if length(refs) >= 2 - last_two = filter(!isnothing, run_infos[(end - 1):end]) + last_two = filter(!isnothing, run_infos[(end-1):end]) length(last_two) == 2 && _warn_env_difference(last_two[1].fingerprint, last_two[2].fingerprint) end println("-"^total_w) @@ -387,7 +387,7 @@ function report_multi_ref(db::SQLite.DB, case_spec::CaseSpec, end println() return (n_ok=n_ok, n_changed=n_changed, n_missing=n_missing, - n_failed=count(identity, failed_mask)) + n_failed=count(identity, failed_mask)) end """ diff --git a/regression-harness/src/types.jl b/regression-harness/src/types.jl index 05c7159ce..bfce92ed7 100644 --- a/regression-harness/src/types.jl +++ b/regression-harness/src/types.jl @@ -19,10 +19,11 @@ end Specification for a test case: what to run and what to extract. `kind` selects the runner backend: + - "gpec_run" (default) — run GPEC end-to-end on `example_dir`, extract from `gpec.h5` - "computed" — run a self-contained Julia computation that writes a small h5 - (no `example_dir` required); used for analytic/reference cases - like the GGJ inner-layer benchmark. + (no `example_dir` required); used for analytic/reference cases + like the GGJ inner-layer benchmark. """ struct CaseSpec name::String diff --git a/regression-harness/src/utils.jl b/regression-harness/src/utils.jl index 01afbd40a..d1110f8ef 100644 --- a/regression-harness/src/utils.jl +++ b/regression-harness/src/utils.jl @@ -130,7 +130,7 @@ newest. Without it, two refs are compared across two different package sets and differences surface as physics regressions. """ function create_worktree(commit_hash::String, repo_root::String; - pin_manifest_from::Union{String,Nothing}=nothing)::String + pin_manifest_from::Union{String,Nothing}=nothing)::String short = commit_hash[1:min(8, length(commit_hash))] worktree_path = tempname() * "_gpec_$(short)" try diff --git a/src/Analysis/Equilibrium.jl b/src/Analysis/Equilibrium.jl index 6dbfede40..51b10f851 100644 --- a/src/Analysis/Equilibrium.jl +++ b/src/Analysis/Equilibrium.jl @@ -219,7 +219,7 @@ function plot_flux_surfaces(h5path; n_psi=11, n_theta=18, save_path=nothing) for s in 1:msing idx = argmin(abs.(xs_rz .- psi_sing[s])) q_label = abs(q_sing[s] - round(q_sing[s])) < 0.05 ? - "q=$(round(Int, q_sing[s]))" : "q=$(round(q_sing[s], digits=2))" + "q=$(round(Int, q_sing[s]))" : "q=$(round(q_sing[s], digits=2))" plot!(p, [R_grid[idx, :]; R_grid[idx, 1]], [Z_grid[idx, :]; Z_grid[idx, 1]]; color=:red, linewidth=1.5, label=s == 1 ? "Rational surface" : "") @@ -368,23 +368,26 @@ function plot_equilibrium_summary(h5path; save_path=nothing) title_str = "q0=$(round(q0,digits=2)) q95=$(round(q95,digits=2)) βₜ=$(round(betat,digits=3)) βₙ=$(round(betan,digits=3)) κ=$(round(kappa,digits=2)) li1=$(round(li1,digits=3))" - p_rz = plot_flux_surfaces(h5path) - p_q = plot_qprofile(h5path; show_singular=true) + p_rz = plot_flux_surfaces(h5path) + p_q = plot_qprofile(h5path; show_singular=true) p_pres = plot_pressure_profile(h5path) - p_f = plot_f_profile(h5path) - p_gse = plot_gse_by_theta(h5path) # includes integrated overplot; nothing if absent + p_f = plot_f_profile(h5path) + p_gse = plot_gse_by_theta(h5path) # includes integrated overplot; nothing if absent # Suppress x-axis labels/ticks on all but the bottom profile panel — they share the # same ψ_N axis and labeling every panel wastes vertical space. hide_xaxis!(p) = plot!(p; xlabel="", xformatter=_->"", bottom_margin=1Plots.mm) if isnothing(p_gse) - hide_xaxis!(p_q); hide_xaxis!(p_pres) + hide_xaxis!(p_q) + hide_xaxis!(p_pres) l = @layout [a{0.38w} [b; c; d]] p = plot(p_rz, p_q, p_pres, p_f; layout=l, size=(1300, 750), plot_title=title_str, plot_titlefontsize=10, top_margin=8Plots.mm) else - hide_xaxis!(p_q); hide_xaxis!(p_pres); hide_xaxis!(p_f) + hide_xaxis!(p_q) + hide_xaxis!(p_pres) + hide_xaxis!(p_f) l = @layout [a{0.38w} [b; c; d; e]] p = plot(p_rz, p_q, p_pres, p_f, p_gse; layout=l, size=(1300, 1000), plot_title=title_str, plot_titlefontsize=10, top_margin=8Plots.mm) diff --git a/src/Analysis/PerturbedEquilibrium.jl b/src/Analysis/PerturbedEquilibrium.jl index 33f8bdc0f..7c1ea2d92 100644 --- a/src/Analysis/PerturbedEquilibrium.jl +++ b/src/Analysis/PerturbedEquilibrium.jl @@ -45,10 +45,10 @@ function plot_resonant_area_weighted_field_amplitude(h5path; save_path=nothing) return plot(; title="No resonant area-weighted field data — run with perturbed equilibrium enabled", legend=false) resonant_area_weighted_field, rational_psi, rational_q, rational_n = h5open(h5path, "r") do fid - read(fid[base * "resonant_area_weighted_field"]), - read(fid[base * "rational_psi"]), - read(fid[base * "rational_q"]), - read(fid[base * "rational_n"]) + read(fid[base*"resonant_area_weighted_field"]), + read(fid[base*"rational_psi"]), + read(fid[base*"rational_q"]), + read(fid[base*"rational_n"]) end p = plot(; xlabel="Norm. Poloidal Flux", ylabel="|b^r| [T]", @@ -96,9 +96,9 @@ function plot_island_widths(h5path; save_path=nothing) return plot(; title="No island width data — run with perturbed equilibrium enabled", legend=false) island_hw, rational_psi, rational_q = h5open(h5path, "r") do fid - read(fid[base * "island_half_width"]), - read(fid[base * "rational_psi"]), - read(fid[base * "rational_q"]) + read(fid[base*"island_half_width"]), + read(fid[base*"rational_psi"]), + read(fid[base*"rational_q"]) end p = scatter( @@ -150,9 +150,9 @@ function plot_chirikov_parameter(h5path; save_path=nothing) return plot(; title="No Chirikov data — run with perturbed equilibrium enabled", legend=false) chirikov, rational_psi, rational_q = h5open(h5path, "r") do fid - read(fid[base * "chirikov_parameter"]), - read(fid[base * "rational_psi"]), - read(fid[base * "rational_q"]) + read(fid[base*"chirikov_parameter"]), + read(fid[base*"rational_psi"]), + read(fid[base*"rational_q"]) end colors = [k > 1.0 ? :red : :steelblue for k in chirikov] @@ -212,10 +212,10 @@ function plot_driven_delta_prime(h5path; save_path=nothing) return plot(; title="No PE Δ' data — run with perturbed equilibrium enabled", legend=false) delta_prime, rational_psi, rational_q, rational_n = h5open(h5path, "r") do fid - read(fid[base * "Delta_prime"]), - read(fid[base * "rational_psi"]), - read(fid[base * "rational_q"]), - read(fid[base * "rational_n"]) + read(fid[base*"Delta_prime"]), + read(fid[base*"rational_psi"]), + read(fid[base*"rational_q"]), + read(fid[base*"rational_n"]) end p = plot(; xlabel="Norm. Poloidal Flux", ylabel="Re(Δ')", @@ -298,10 +298,10 @@ function _plot_resonant_current(h5path) return plot(; title="No resonant current data", legend=false) resonant_current, rational_psi, rational_q, rational_n = h5open(h5path, "r") do fid - read(fid[base * "resonant_current"]), - read(fid[base * "rational_psi"]), - read(fid[base * "rational_q"]), - read(fid[base * "rational_n"]) + read(fid[base*"resonant_current"]), + read(fid[base*"rational_psi"]), + read(fid[base*"rational_q"]), + read(fid[base*"rational_n"]) end p = plot(; xlabel="Norm. Poloidal Flux", ylabel="|I_res|", @@ -352,10 +352,10 @@ A `Plots.jl` plot object. """ function plot_mode_spectrogram(h5path; component=:xi_psi, save_path=nothing) comp_map = Dict( - :xi_psi => "xi_psi", - :b_psi => "b_psi_area_weighted", # area-normalized b^ψ + :xi_psi => "xi_psi", + :b_psi => "b_psi_area_weighted", # area-normalized b^ψ :b_theta => "b_theta", - :b_zeta => "b_zeta", + :b_zeta => "b_zeta" ) haskey(comp_map, component) || error("component must be one of :xi_psi, :b_psi, :b_theta, :b_zeta") @@ -439,9 +439,9 @@ Three-panel composite summary of perturbed equilibrium results: A `Plots.jl` plot object. """ function plot_perturbed_equilibrium_summary(h5path; save_path=nothing) - p_islands = plot_resonant_area_weighted_field_amplitude(h5path) - p_bpsi = _plot_bpsi_edge_spectrum(h5path) - p_spectro = plot_mode_spectrogram(h5path; component=:xi_psi) + p_islands = plot_resonant_area_weighted_field_amplitude(h5path) + p_bpsi = _plot_bpsi_edge_spectrum(h5path) + p_spectro = plot_mode_spectrogram(h5path; component=:xi_psi) l = @layout [grid(1, 2){0.35h}; b] p = plot(p_islands, p_bpsi, p_spectro; layout=l, size=(1100, 1100)) @@ -457,11 +457,11 @@ function _plot_bpsi_edge_spectrum(h5path) return plot(; title="No b_psi data — run with perturbed equilibrium enabled", legend=false) data, mlow, mhigh = h5open(h5path, "r") do fid - read(fid[base * "b_psi_area_weighted"]), + read(fid[base*"b_psi_area_weighted"]), read(fid["Info/mlow"]), read(fid["Info/mhigh"]) end - mpert = mhigh - mlow + 1 + mpert = mhigh - mlow + 1 m_vals = mlow:mhigh bpsi_edge = abs.(data[end, 1:mpert]) diff --git a/src/Analysis/PerturbedEquilibriumModes.jl b/src/Analysis/PerturbedEquilibriumModes.jl index 58aacdaf9..b63ac97e2 100644 --- a/src/Analysis/PerturbedEquilibriumModes.jl +++ b/src/Analysis/PerturbedEquilibriumModes.jl @@ -20,33 +20,37 @@ Reads all required metadata (mlow, nlow, mpert, npert) and spline data (ν) from the HDF5 file. # Arguments -- `h5_file::String`: Path to gpec.h5 output file -- `variable::String`: HDF5 dataset path, e.g. `"PerturbedEquilibrium/Response/xi_R"` + + - `h5_file::String`: Path to gpec.h5 output file + - `variable::String`: HDF5 dataset path, e.g. `"PerturbedEquilibrium/Response/xi_R"` # Keyword arguments -- `mtheta::Int`: theta grid resolution (default: `max(2*(|mlow|+mpert), 512)`) -- `keep_sfl_phi::Bool`: if `true` (default), output in SFL toroidal angle; - if `false`, apply `exp(i*n*ν(ψ,θ))` to convert to machine toroidal angle - and conjugate if `helicity > 0` (matches Fortran `gpout_xbrzphifun`) + + - `mtheta::Int`: theta grid resolution (default: `max(2*(|mlow|+mpert), 512)`) + - `keep_sfl_phi::Bool`: if `true` (default), output in SFL toroidal angle; + if `false`, apply `exp(i*n*ν(ψ,θ))` to convert to machine toroidal angle + and conjugate if `helicity > 0` (matches Fortran `gpout_xbrzphifun`) # Returns -- `theta_data::Array{ComplexF64,3}`: `[npsi × mtheta × npert]` -- `theta_grid::Vector{Float64}`: `[mtheta]` SFL theta ∈ [0, 1) -- `n_vals::Vector{Int}`: `[npert]` toroidal mode numbers + + - `theta_data::Array{ComplexF64,3}`: `[npsi × mtheta × npert]` + - `theta_grid::Vector{Float64}`: `[mtheta]` SFL theta ∈ [0, 1) + - `n_vals::Vector{Int}`: `[npert]` toroidal mode numbers !!! note + When used on the cylindrical components `xi_R`, `xi_Z`, `xi_phi`, `b_R`, `b_Z`, `b_phi` these are currently in beta and show up to ~20% discrepancies vs Fortran. """ function modes_to_theta(h5_file::String, variable::String; - mtheta::Union{Int,Nothing}=nothing, - keep_sfl_phi::Bool=true) + mtheta::Union{Int,Nothing}=nothing, + keep_sfl_phi::Bool=true) h5open(h5_file, "r") do f modes = read(f, variable) # (npsi, numpert_total) npsi, numpert_total = size(modes) - mlow = read(f, "Info/mlow") - nlow = read(f, "Info/nlow") + mlow = read(f, "Info/mlow") + nlow = read(f, "Info/nlow") mpert = read(f, "Info/mpert") npert = read(f, "Info/npert") @assert numpert_total == mpert * npert "Expected numpert_total=$(mpert*npert), got $numpert_total" @@ -58,7 +62,7 @@ function modes_to_theta(h5_file::String, variable::String; theta_data = zeros(ComplexF64, npsi, mth, npert) for k in 1:npert - col_range = (k-1)*mpert+1 : k*mpert + col_range = ((k-1)*mpert+1):(k*mpert) for ipsi in 1:npsi theta_data[ipsi, :, k] .= inverse(ft, view(modes, ipsi, col_range)) end @@ -68,7 +72,7 @@ function modes_to_theta(h5_file::String, variable::String; # Reconstruct ν spline from stored grid + nodal values (FastInterpolations v0.4 API) rzphi_xs = read(f, "Equilibrium/Geometry/psi") rzphi_ys = read(f, "Equilibrium/Geometry/theta") - nu_vals = read(f, "Equilibrium/Geometry/nu") + nu_vals = read(f, "Equilibrium/Geometry/nu") nu_spline = cubic_interp( (rzphi_xs, rzphi_ys), nu_vals; bc=(CubicFit(), PeriodicBC()), @@ -77,8 +81,8 @@ function modes_to_theta(h5_file::String, variable::String; psi_grid = read(f, "ForceFreeStates/Solutions/ForwardIntegration/psi") - bt_sign = haskey(f, "Equilibrium/B_T_sign") ? read(f, "Equilibrium/B_T_sign") : 1 - crnt = haskey(f, "Equilibrium/I_p") ? read(f, "Equilibrium/I_p") : 1.0 + bt_sign = haskey(f, "Equilibrium/B_T_sign") ? read(f, "Equilibrium/B_T_sign") : 1 + crnt = haskey(f, "Equilibrium/I_p") ? read(f, "Equilibrium/I_p") : 1.0 helicity = bt_sign * Int(sign(crnt)) hint = (Ref(1), Ref(1)) @@ -110,18 +114,21 @@ Extend theta-space data to a `(θ, φ)` grid via toroidal inverse DFT. f(θ, φ) = Σₙ fₙ(θ) exp(i·n·φ) # Arguments -- `theta_data::Array{ComplexF64,3}`: `[npsi × mtheta × npert]` from `modes_to_theta` -- `n_vals::Vector{Int}`: toroidal mode numbers + + - `theta_data::Array{ComplexF64,3}`: `[npsi × mtheta × npert]` from `modes_to_theta` + - `n_vals::Vector{Int}`: toroidal mode numbers # Keyword arguments -- `nphi::Int`: toroidal grid points (default: `max(4*maximum(abs.(n_vals)), 64)`) + + - `nphi::Int`: toroidal grid points (default: `max(4*maximum(abs.(n_vals)), 64)`) # Returns -- `full_data::Array{ComplexF64,3}`: `[npsi × mtheta × nphi]` -- `phi_grid::Vector{Float64}`: `[nphi]` in radians ∈ [0, 2π) + + - `full_data::Array{ComplexF64,3}`: `[npsi × mtheta × nphi]` + - `phi_grid::Vector{Float64}`: `[nphi]` in radians ∈ [0, 2π) """ function theta_to_thetaphi(theta_data::Array{ComplexF64,3}, n_vals::Vector{Int}; - nphi::Union{Int,Nothing}=nothing) + nphi::Union{Int,Nothing}=nothing) npsi, mth, npert = size(theta_data) np = isnothing(nphi) ? max(4 * maximum(abs.(n_vals)), 64) : nphi phi_grid = [(j - 1) * 2π / np for j in 1:np] diff --git a/src/Equilibrium/AnalyticEquilibrium.jl b/src/Equilibrium/AnalyticEquilibrium.jl index 72a16a05c..7ed653867 100644 --- a/src/Equilibrium/AnalyticEquilibrium.jl +++ b/src/Equilibrium/AnalyticEquilibrium.jl @@ -243,7 +243,7 @@ function tj_analytic_f1(x::Float64, nu::Float64, qc::Float64) if x < 0.1 x2 = x * x return x2 * (1 - (nu-1)*x2/2 + (nu-1)*(nu-2)*x2*x2/6 - - (nu-1)*(nu-2)*(nu-3)*x2*x2*x2/24) / qc + (nu-1)*(nu-2)*(nu-3)*x2*x2*x2/24) / qc else return (1 - (1 - x*x)^nu) / (nu * qc) end @@ -259,10 +259,10 @@ parameterization. function tj_analytic_f1p(x::Float64, nu::Float64, qc::Float64) if x < 0.1 x2 = x * x - return 2*x * (1 - (nu-1)*x2 + (nu-1)*(nu-2)*x2*x2/2 - - (nu-1)*(nu-2)*(nu-3)*x2*x2*x2/6) / qc + return 2 * x * (1 - (nu-1)*x2 + (nu-1)*(nu-2)*x2*x2/2 - + (nu-1)*(nu-2)*(nu-3)*x2*x2*x2/6) / qc else - return 2*x * (1 - x*x)^(nu-1) / qc + return 2 * x * (1 - x*x)^(nu-1) / qc end end @@ -273,10 +273,11 @@ GPEC adaptation of the analytic shape ODE used in R. Fitzpatrick's TJ code `tj_analytic_run_direct` call so both pipelines share identical numerics. Fields: + - physical: a, R0, qc, mu, pc, B0 - derived: epsa2 = (a/R0)² - near-axis BC constants: rmin, x0 = rmin, r0 = rmin·a, f1c = 1/qc, - p2ppc = d²p₂/dx²|_0 = −2·μ·pc + p2ppc = d²p₂/dx²|_0 = −2·μ·pc """ struct TJAnalyticShapeParams a::Float64 @@ -293,15 +294,15 @@ struct TJAnalyticShapeParams p2ppc::Float64 end -function TJAnalyticShapeParams(tj::TJAnalyticConfig; rmin::Float64 = 1e-4) +function TJAnalyticShapeParams(tj::TJAnalyticConfig; rmin::Float64=1e-4) a, R0 = tj.lar_a, tj.lar_r0 - mu = max(tj.mu, 1.001) + mu = max(tj.mu, 1.001) return TJAnalyticShapeParams( a, R0, tj.qc, mu, tj.pc, tj.B0, (a / R0)^2, rmin, rmin, rmin * a, 1.0 / tj.qc, - -2.0 * mu * tj.pc, + -2.0 * mu * tj.pc ) end @@ -315,9 +316,9 @@ The params argument carries TJAnalyticShapeParams fields plus the current `nu`. """ function tj_analytic_shape_rhs!(dy, y, params, r) (; a, B0, qc, mu, pc, epsa2, nu) = params - x = r / a + x = r / a xfac = max(1 - x^2, 0.0) - f1 = tj_analytic_f1(x, nu, qc) + f1 = tj_analytic_f1(x, nu, qc) f1px = tj_analytic_f1p(x, nu, qc) p2px = -2 * mu * pc * x * xfac^(mu - 1) @@ -340,16 +341,19 @@ function tj_analytic_shape_rhs!(dy, y, params, r) # f₃'(x) for Hₙ = Vₙ = 0 (n ≥ 2 harmonics rescaled to zero, as in the # TJ-analytic benchmark configuration of Fitzpatrick's TJ code). g2, f3 = y[2], y[5] - f3p_x = -f3 * f1px / f1 - - f1 * (3 * x^2 / 2 - 2 * x * H1p + H1p^2) / x + - f1px * (g2 - 3 * x^2 / 4 + H1 + 3 * H1p^2 / 2) + - x^2 * p2px * (g2 + x^2 / 2 - 3 * x * H1p - 2 * H1) / f1 + f3p_x = + -f3 * f1px / f1 - + f1 * (3 * x^2 / 2 - 2 * x * H1p + H1p^2) / x + + f1px * (g2 - 3 * x^2 / 4 + H1 + 3 * H1p^2 / 2) + + x^2 * p2px * (g2 + x^2 / 2 - 3 * x * H1p - 2 * H1) / f1 dy[5] = f3p_x / a return nothing end -"""Initial conditions at x = x0, matching the TJ-analytic model's near-axis -expansion (cf. R. Fitzpatrick's TJ code, https://github.com/rfitzp/TJ).""" +""" +Initial conditions at x = x0, matching the TJ-analytic model's near-axis +expansion (cf. R. Fitzpatrick's TJ code, https://github.com/rfitzp/TJ). +""" function tj_analytic_shape_initial(p::TJAnalyticShapeParams, nu::Float64) f1_0 = tj_analytic_f1(p.x0, nu, p.qc) y0 = zeros(5) @@ -368,14 +372,14 @@ downstream Hₙ / ψ splines sit on uniform nodes); leave it `nothing` for the default adaptive save pattern used by `tj_analytic_run`. """ function tj_analytic_shape_solve(p::TJAnalyticShapeParams, nu::Float64; - reltol::Float64 = 1e-7, abstol::Float64 = 1e-8, - saveat = nothing) - rhs_params = (; p.a, p.B0, p.qc, p.mu, p.pc, p.epsa2, nu = nu) + reltol::Float64=1e-7, abstol::Float64=1e-8, + saveat=nothing) + rhs_params = (; p.a, p.B0, p.qc, p.mu, p.pc, p.epsa2, nu=nu) prob = ODEProblem(tj_analytic_shape_rhs!, tj_analytic_shape_initial(p, nu), (p.r0, p.a), rhs_params) if saveat === nothing - return solve(prob, Vern9(); reltol, abstol, maxiters = 10000, dense = false) + return solve(prob, Vern9(); reltol, abstol, maxiters=10000, dense=false) else - return solve(prob, Vern9(); reltol, abstol, maxiters = 10000, saveat = saveat) + return solve(prob, Vern9(); reltol, abstol, maxiters=10000, saveat=saveat) end end @@ -389,9 +393,9 @@ O(εa²) correction relative to the lowest-order guess ν = qa/qc, which matters for the TJ-analytic benchmark at large ε. Falls back to the lowest-order ν if the bracket search diverges. """ -function tj_analytic_find_nu(p::TJAnalyticShapeParams, qa_target::Float64; reltol::Float64 = 1e-7) +function tj_analytic_find_nu(p::TJAnalyticShapeParams, qa_target::Float64; reltol::Float64=1e-7) function q2_edge(nu::Float64) - sol = tj_analytic_shape_solve(p, nu; reltol) + sol = tj_analytic_shape_solve(p, nu; reltol) g2end = sol.u[end][2] f3end = sol.u[end][5] f1end = tj_analytic_f1(1.0, nu, p.qc) @@ -400,7 +404,7 @@ function tj_analytic_find_nu(p::TJAnalyticShapeParams, qa_target::Float64; relto nu_guess = qa_target / p.qc return try find_zero(nu -> q2_edge(nu) - qa_target, (0.5 * nu_guess, 2 * nu_guess); - atol = 1e-8, rtol = 1e-10) + atol=1e-8, rtol=1e-10) catch err @warn "ν root-find failed for TJ-analytic equilibrium; falling back to lowest-order ν = qa/qc" error = err nu_guess @@ -443,16 +447,16 @@ included; they are zero in the TJ-analytic benchmark scans. Reference: R. Fitzpatrick, TJ code, https://github.com/rfitzp/TJ """ function tj_analytic_run(equil_input::EquilibriumConfig, tj::TJAnalyticConfig) - a, R0 = tj.lar_a, tj.lar_r0 + a, R0 = tj.lar_a, tj.lar_r0 qc, mu = tj.qc, max(tj.mu, 1.001) pc, B0 = tj.pc, tj.B0 ma, mtau = tj.ma, tj.mtau p = TJAnalyticShapeParams(tj) - epsa2 = p.epsa2 - p00_phys = B0^2 * epsa2 * pc # μ₀P = B₀²·εa²·p₂ at axis + epsa2 = p.epsa2 + p00_phys = B0^2 * epsa2 * pc # μ₀P = B₀²·εa²·p₂ at axis - nu = tj_analytic_find_nu(p, tj.qa; reltol = equil_input.etol) - sol = tj_analytic_shape_solve(p, nu; reltol = equil_input.etol) + nu = tj_analytic_find_nu(p, tj.qa; reltol=equil_input.etol) + sol = tj_analytic_shape_solve(p, nu; reltol=equil_input.etol) r_arr = sol.t y_mat = reduce(hcat, sol.u)' @@ -468,7 +472,7 @@ function tj_analytic_run(equil_input::EquilibriumConfig, tj::TJAnalyticConfig) xfac = max(1 - x^2, 0.0) f1 = tj_analytic_f1(x, nu, qc) - ψ = y_mat[i, 1] + ψ = y_mat[i, 1] g2 = y_mat[i, 2] H1 = y_mat[i, 3] f3 = y_mat[i, 5] @@ -507,7 +511,7 @@ function tj_analytic_run(equil_input::EquilibriumConfig, tj::TJAnalyticConfig) f = spl(r; hint=hint) # f[1]=F, f[2]=P, f[3]=q, f[4]=ψ, f[5]=g₂, f[6]=H₁ - sq_xs[ia] = f[4] / psio + sq_xs[ia] = f[4] / psio sq_fs[ia, 1] = f[1] # F sq_fs[ia, 2] = f[2] # P sq_fs[ia, 3] = f[3] # q @@ -525,7 +529,7 @@ function tj_analytic_run(equil_input::EquilibriumConfig, tj::TJAnalyticConfig) for itau in 1:(mtau+1) θ = 2π * (itau - 1) / mtau rzphi_fs_nodes[ia, itau, 1] = R0 + Δ + α * r * cos(θ) - rzphi_fs_nodes[ia, itau, 2] = α * r * sin(θ) + rzphi_fs_nodes[ia, itau, 2] = α * r * sin(θ) end end @@ -579,38 +583,38 @@ ODE (g₂, H₁, H₁', f₃), the `GetPSIvac` / `GetHHvac` vacuum extension, an EFIT-writer (R, Z) → (r, w) Newton inversion that this routine adapts. """ function tj_analytic_run_direct(equil_input::EquilibriumConfig, tj::TJAnalyticConfig; - nrbox::Int = 257, nzbox::Int = 257, rc::Float64 = 1.2) - a, R0 = tj.lar_a, tj.lar_r0 + nrbox::Int=257, nzbox::Int=257, rc::Float64=1.2) + a, R0 = tj.lar_a, tj.lar_r0 qc, mu = tj.qc, max(tj.mu, 1.001) pc, B0 = tj.pc, tj.B0 p = TJAnalyticShapeParams(tj) epsa, epsa2 = p.a / p.R0, p.epsa2 - p00_phys = B0^2 * epsa2 * pc + p00_phys = B0^2 * epsa2 * pc # ν root-find (cf. Fitzpatrick TJ's Setnu): q₂(1) = qa_target. - nu = tj_analytic_find_nu(p, tj.qa; reltol = equil_input.etol) + nu = tj_analytic_find_nu(p, tj.qa; reltol=equil_input.etol) # Dense saveat so the downstream splines (H₁, g₂, f₃, ψ) are evaluated on # a fine uniform r grid rather than the ~30 adaptive Vern9 steps — otherwise # the (R, Z) → (r, w) Newton iteration hits spline interpolation artifacts. - dense_r = collect(range(p.r0, p.a; length = 1024)) - sol = tj_analytic_shape_solve(p, nu; reltol = equil_input.etol, - abstol = 1e-10, saveat = dense_r) - r_arr = sol.t - y_mat = reduce(hcat, sol.u)' + dense_r = collect(range(p.r0, p.a; length=1024)) + sol = tj_analytic_shape_solve(p, nu; reltol=equil_input.etol, + abstol=1e-10, saveat=dense_r) + r_arr = sol.t + y_mat = reduce(hcat, sol.u)' # Radial splines in the TJ-analytic dimensionless x = r/a on a clean grid for H₁ etc. x_nodes = r_arr ./ a - ψ_of_r = cubic_interp(r_arr, y_mat[:, 1]; extrap=ExtendExtrap()) - H1_of_x = cubic_interp(x_nodes, y_mat[:, 3]; extrap=ExtendExtrap()) + ψ_of_r = cubic_interp(r_arr, y_mat[:, 1]; extrap=ExtendExtrap()) + H1_of_x = cubic_interp(x_nodes, y_mat[:, 3]; extrap=ExtendExtrap()) H1p_of_x = cubic_interp(x_nodes, y_mat[:, 4]; extrap=ExtendExtrap()) - g2_of_x = cubic_interp(x_nodes, y_mat[:, 2]; extrap=ExtendExtrap()) - f3_of_x = cubic_interp(x_nodes, y_mat[:, 5]; extrap=ExtendExtrap()) + g2_of_x = cubic_interp(x_nodes, y_mat[:, 2]; extrap=ExtendExtrap()) + f3_of_x = cubic_interp(x_nodes, y_mat[:, 5]; extrap=ExtendExtrap()) # Edge values needed by GetPSIvac - f1a = tj_analytic_f1(1.0, nu, qc) - f3a = f3_of_x(1.0) - H1a = H1_of_x(1.0) + f1a = tj_analytic_f1(1.0, nu, qc) + f3a = f3_of_x(1.0) + H1a = H1_of_x(1.0) H1ap = H1p_of_x(1.0) psio = ψ_of_r(a) # ψ at r = a (boundary) @@ -644,7 +648,7 @@ function tj_analytic_run_direct(equil_input::EquilibriumConfig, tj::TJAnalyticCo return f_R_shift(rc - 1e-8, w) * r^2 / rc^2 end H1 = (r < 1.0) ? H1_of_x(r) : H1_vac(r) - L = r^3 / 8 - r * H1 / 2 + L = r^3 / 8 - r * H1 / 2 return epsa2 * H1 + epsa2 * epsa * L * cos(w) end function f_Z_shift(r::Float64, w::Float64) @@ -652,7 +656,7 @@ function tj_analytic_run_direct(equil_input::EquilibriumConfig, tj::TJAnalyticCo return f_Z_shift(rc - 1e-8, w) * r^2 / rc^2 end H1 = (r < 1.0) ? H1_of_x(r) : H1_vac(r) - L = r^3 / 8 - r * H1 / 2 + L = r^3 / 8 - r * H1 / 2 return -epsa2 * epsa * L * sin(w) end @@ -699,9 +703,9 @@ function tj_analytic_run_direct(equil_input::EquilibriumConfig, tj::TJAnalyticCo # Grid spans R₀ ± rc·a × ±rc·a (where rc is the vacuum-shell radius in # units of a), giving a comfortable margin for the separatrix finder. r_span = rc * a - psi_in_xs = collect(range(R0 - r_span, R0 + r_span; length = nrbox)) - psi_in_ys = collect(range(-r_span, r_span; length = nzbox)) - psi_rz = zeros(Float64, nrbox, nzbox) + psi_in_xs = collect(range(R0 - r_span, R0 + r_span; length=nrbox)) + psi_in_ys = collect(range(-r_span, r_span; length=nzbox)) + psi_rz = zeros(Float64, nrbox, nzbox) for i in 1:nrbox, j in 1:nzbox R_norm = psi_in_xs[i] / R0 @@ -724,8 +728,10 @@ function tj_analytic_run_direct(equil_input::EquilibriumConfig, tj::TJAnalyticCo # 1D profile spline, same layout as read_efit (4 columns). Use the # TJ-analytic q₂ on the radial grid so that the prescribed q is # consistent with the ψ(R,Z) we just constructed. - psi_norm_grid = range(0.0, 1.0; length = nrbox) - F_nodes = zeros(nrbox); P_nodes = zeros(nrbox); q_nodes = zeros(nrbox) + psi_norm_grid = range(0.0, 1.0; length=nrbox) + F_nodes = zeros(nrbox) + P_nodes = zeros(nrbox) + q_nodes = zeros(nrbox) for i in 1:nrbox ψN = psi_norm_grid[i] # Invert ψN = (ψ_plasma(r) - 0) / psio ⇒ find r such that ψ_plasma(r) = ψN·psio. @@ -746,7 +752,7 @@ function tj_analytic_run_direct(equil_input::EquilibriumConfig, tj::TJAnalyticCo F_nodes[i] = R0 * B0 * (1 + epsa2 * g2_val) P_nodes[i] = p00_phys * xfac^mu q_nodes[i] = (x > 1e-10) ? x^2 * (1 + epsa2 * g2_val) * - exp(-epsa2 * f3_val / f1) / f1 : qc + exp(-epsa2 * f3_val / f1) / f1 : qc end sq_fs_nodes = hcat(F_nodes, P_nodes, q_nodes, sqrt.(collect(psi_norm_grid))) sq_in = cubic_interp(collect(psi_norm_grid), Series(sq_fs_nodes); extrap=ExtendExtrap()) @@ -756,7 +762,7 @@ function tj_analytic_run_direct(equil_input::EquilibriumConfig, tj::TJAnalyticCo # Analytic: ingest=nothing — replay regenerates from the [TJ_ANALYTIC_INPUT] TOML section. return DirectRunInput(equil_input, sq_in, psi_in, psi_in_xs, psi_in_ys, - rmin_grid, rmax_grid, zmin_grid, zmax_grid, psio, 1, nothing) + rmin_grid, rmax_grid, zmin_grid, zmax_grid, psio, 1, nothing) end """ diff --git a/src/Equilibrium/DirectEquilibriumArcLength.jl b/src/Equilibrium/DirectEquilibriumArcLength.jl index 32b93a0ac..f247da7a1 100644 --- a/src/Equilibrium/DirectEquilibriumArcLength.jl +++ b/src/Equilibrium/DirectEquilibriumArcLength.jl @@ -64,11 +64,11 @@ end Arc-length-parameterized flux surface integration. Drop-in replacement for `direct_fieldline_int` with identical return format: -- `y_out[:, 1]`: geometric angle η ∈ 0 to 2π (CCW from outboard midplane) -- `y_out[:, 2]`: accumulated ∫dl/Bp -- `y_out[:, 3]`: rfac = √((R−ro)² + (Z−zo)²) -- `y_out[:, 4]`: accumulated ∫dl/(R²Bp) -- `y_out[:, 5]`: accumulated ∫jac·dl/Bp + - `y_out[:, 1]`: geometric angle η ∈ 0 to 2π (CCW from outboard midplane) + - `y_out[:, 2]`: accumulated ∫dl/Bp + - `y_out[:, 3]`: rfac = √((R−ro)² + (Z−zo)²) + - `y_out[:, 4]`: accumulated ∫dl/(R²Bp) + - `y_out[:, 5]`: accumulated ∫jac·dl/Bp The ODE is terminated by a `ContinuousCallback` that detects the return to the outboard midplane (Z = zo, R > ro) after a minimum arc-length guard. @@ -144,4 +144,3 @@ outboard midplane (Z = zo, R > ro) after a minimum arc-length guard. # bfield at the starting point carries F and P for the surface-averaged quantities return y_out, bfield end - diff --git a/src/Equilibrium/Equilibrium.jl b/src/Equilibrium/Equilibrium.jl index eed157812..6b55898ad 100644 --- a/src/Equilibrium/Equilibrium.jl +++ b/src/Equilibrium/Equilibrium.jl @@ -330,10 +330,10 @@ function equilibrium_global_parameters!(pe::PlasmaEquilibrium) P_vals = profiles.P_spline.y dVdpsi_vals = profiles.dVdpsi_spline.y - fsi_pdv = fsi(P_vals .* dVdpsi_vals) # ∫ p dV/dψ - fsi_dv = fsi(dVdpsi_vals) # ∫ dV/dψ + fsi_pdv = fsi(P_vals .* dVdpsi_vals) # ∫ p dV/dψ + fsi_dv = fsi(dVdpsi_vals) # ∫ dV/dψ fsi_p2dv = fsi(P_vals .^ 2 .* dVdpsi_vals) # ∫ p² dV/dψ - volume = fsi_dv # same integrand as hs col 2 in Fortran + volume = fsi_dv # same integrand as hs col 2 in Fortran # Poloidal-field surface integral hs_bp2(ψ) = ψ₀² ∮dθ |∇ψ|² / (R² J). # This is Fortran equil_out.f's hs%fs(:,3) and is the correct integrand for @@ -343,21 +343,21 @@ function equilibrium_global_parameters!(pe::PlasmaEquilibrium) for ipsi in 0:mpsi acc = 0.0 for itheta in 0:mtheta - r2 = pe.rzphi_rsquared.nodal_derivs.partials[1, ipsi+1, itheta+1] - offset = pe.rzphi_offset.nodal_derivs.partials[1, ipsi+1, itheta+1] - jac = pe.rzphi_jac.nodal_derivs.partials[1, ipsi+1, itheta+1] - r2_y = pe.rzphi_rsquared.nodal_derivs.partials[3, ipsi+1, itheta+1] - offset_y = pe.rzphi_offset.nodal_derivs.partials[3, ipsi+1, itheta+1] + r2 = pe.rzphi_rsquared.nodal_derivs.partials[1, ipsi+1, itheta+1] + offset = pe.rzphi_offset.nodal_derivs.partials[1, ipsi+1, itheta+1] + jac = pe.rzphi_jac.nodal_derivs.partials[1, ipsi+1, itheta+1] + r2_y = pe.rzphi_rsquared.nodal_derivs.partials[3, ipsi+1, itheta+1] + offset_y = pe.rzphi_offset.nodal_derivs.partials[3, ipsi+1, itheta+1] jacfac = π / jac - rfac = sqrt(r2) - eta = 2π * (pe.rzphi_ys[itheta+1] + offset) - r = pe.ro + rfac * cos(eta) - v21 = jacfac * r2_y / (2π * rfac) - v22 = jacfac * (1 + offset_y) * (2 * rfac) - v33 = jacfac * 2π * (r / π) - dvsq = (v21^2 + v22^2) * (v33 * jac^2)^2 - acc += dvsq / (r^2) / jac + rfac = sqrt(r2) + eta = 2π * (pe.rzphi_ys[itheta+1] + offset) + r = pe.ro + rfac * cos(eta) + v21 = jacfac * r2_y / (2π * rfac) + v22 = jacfac * (1 + offset_y) * (2 * rfac) + v33 = jacfac * 2π * (r / π) + dvsq = (v21^2 + v22^2) * (v33 * jac^2)^2 + acc += dvsq / (r^2) / jac end # Periodic trapezoidal rule on uniform θ grid reduces to a plain mean # because the first and last grid points coincide — matches the int1/int2 @@ -367,15 +367,15 @@ function equilibrium_global_parameters!(pe::PlasmaEquilibrium) fsi_bp2 = fsi(hs_bp2) p0 = P_vals[1] - profiles.P_deriv(profiles.xs[1]; hint=Ref(1)) * profiles.xs[1] # linear extrapolation - betat = 2 * (fsi_pdv / fsi_dv) / bt0^2 - betaj = 2 * sqrt(fsi_p2dv / fsi_dv) / bwall^2 - betan = 100 * amean * bt0 * betat / crnt + betat = 2 * (fsi_pdv / fsi_dv) / bt0^2 + betaj = 2 * sqrt(fsi_p2dv / fsi_dv) / bwall^2 + betan = 100 * amean * bt0 * betat / crnt betap1 = 2 * (fsi_pdv / fsi_dv) / bp0^2 betap2 = 4 * fsi_pdv / ((1e6 * mu0 * crnt)^2 * pe.ro) betap3 = 4 * fsi_pdv / ((1e6 * mu0 * crnt)^2 * rmean) - li1 = fsi_bp2 / fsi_dv / bp0^2 - li2 = 2 * fsi_bp2 / ((1e6 * mu0 * crnt)^2 * pe.ro) - li3 = 2 * fsi_bp2 / ((1e6 * mu0 * crnt)^2 * rmean) + li1 = fsi_bp2 / fsi_dv / bp0^2 + li2 = 2 * fsi_bp2 / ((1e6 * mu0 * crnt)^2 * pe.ro) + li3 = 2 * fsi_bp2 / ((1e6 * mu0 * crnt)^2 * rmean) pe.params.psi0 = psio pe.params.psi_axis = pe.psio diff --git a/src/Equilibrium/EquilibriumTypes.jl b/src/Equilibrium/EquilibriumTypes.jl index 344f5a60f..d6d8e16b8 100644 --- a/src/Equilibrium/EquilibriumTypes.jl +++ b/src/Equilibrium/EquilibriumTypes.jl @@ -245,7 +245,9 @@ A mutable struct holding parameters for the Large Aspect Ratio (LAR) plasma equi zeroth::Bool = false end -"Build a `LargeAspectRatioConfig` from a parsed `[LAR_INPUT]` TOML table." +""" +Build a `LargeAspectRatioConfig` from a parsed `[LAR_INPUT]` TOML table. +""" function LargeAspectRatioConfig(input_dict::Dict{String,Any}) return LargeAspectRatioConfig(; symbolize_keys(input_dict)...) end @@ -285,7 +287,9 @@ Reference: R. Fitzpatrick, TJ code, https://github.com/rfitzp/TJ zeroth::Bool = false # If true, suppress Shafranov shift end -"Build a `TJAnalyticConfig` from a parsed `[TJ_ANALYTIC_INPUT]` TOML table." +""" +Build a `TJAnalyticConfig` from a parsed `[TJ_ANALYTIC_INPUT]` TOML table. +""" function TJAnalyticConfig(input_dict::Dict{String,Any}) return TJAnalyticConfig(; symbolize_keys(input_dict)...) end @@ -321,7 +325,9 @@ A mutable struct holding parameters for the Solev'ev (SOL) plasma equilibrium mo f0fac::Float64 = 1 # scale toroidal field at constant pressure (s*f. beta,q changes. Phi,p,bp constant) end -"Build a `SolovevConfig` from a parsed `[SOL_INPUT]` TOML table." +""" +Build a `SolovevConfig` from a parsed `[SOL_INPUT]` TOML table. +""" function SolovevConfig(input_dict::Dict{String,Any}) return SolovevConfig(; symbolize_keys(input_dict)...) end @@ -419,6 +425,7 @@ raw equilibrium data and preparing the initial splines. 2. `μ₀ * Pressure` — plasma pressure (non-negative) [T²] 3. `q` — safety factor profile 4. `√ψ_norm` — square root of normalized flux + - `psi_in` 2D cubic interpolant on the (R, Z) grid [m]. The values correspond to the **poloidal flux** adjusted to be zero at the boundary [Wb/rad]. @@ -430,14 +437,23 @@ raw equilibrium data and preparing the initial splines. * 1D profiles are represented by `CubicInterpolant` or `CubicSeriesInterpolant` * 2D flux surfaces by `CubicInterpolantND` + - `psi_in_xs::Vector{Float64}` — R coordinate grid for psi_in [m] + - `psi_in_ys::Vector{Float64}` — Z coordinate grid for psi_in [m] + - `rmin::Float64` — Minimum R-coordinate of the computational grid [m] + - `rmax::Float64` — Maximum R-coordinate of the computational grid [m] + - `zmin::Float64` — Minimum Z-coordinate of the computational grid [m] + - `zmax::Float64` — Maximum Z-coordinate of the computational grid [m] + - `psio::Float64` — Total flux difference `|ψ_axis - ψ_boundary|` [Wb/rad] + - `bt_sign::Int` — Sign of the toroidal field (+1 or -1); read from fpol sign in EFIT g-files + - `ingest::EquilibriumIngest` — captured raw arrays for the `gpec.h5` rerun snapshot (a [`DirectIngest`](@ref) for file-based reads, or `nothing` for analytic equilibria) - `psihigh_resolved::Float64` — outer flux limit the equilibrium is formed on: `config.psihigh` @@ -749,7 +765,7 @@ function GeometryProfileSplines(xs::Vector{Float64}, GeometryProfileSplines{typeof(area_spline)}( xs, npts, npts - 1, - area_spline, avg_r_spline, avg_R_spline, + area_spline, avg_r_spline, avg_R_spline ) end @@ -828,7 +844,7 @@ function KineticProfileSplines(xs::Vector{Float64}, xs, npts, npts - 1, ni_spline, ne_spline, Ti_spline, Te_spline, omegaE_spline, loglam_spline, nui_spline, nue_spline, zeff_spline, - ni_deriv, ne_deriv, Ti_deriv, Te_deriv, + ni_deriv, ne_deriv, Ti_deriv, Te_deriv ) end @@ -845,17 +861,21 @@ This object provides a complete representation of the processed plasma equilibri - `params::EquilibriumParameters`: Computed equilibrium parameters and diagnostics. + - `profiles::ProfileSplines`: Named 1D profile splines (F, P, dV/dψ, q) on normalized psi grid. Access values at grid points via `profiles.F_spline.y[i]`, etc. Access derivatives via `profiles.F_deriv.y[i]` or `profiles.F_deriv(psi)`. + - `geometry::GeometryProfileSplines`: Named 1D splines for flux-surface-averaged geometry (area, ⟨r⟩, ⟨R⟩), populated automatically by `compute_geometry_profiles` during construction. + - **Grid coordinates (shared by all rzphi/eqfun interpolants):** + `rzphi_xs::Vector{Float64}`: ψ coordinates (length mpsi+1) + `rzphi_ys::Vector{Float64}`: θ coordinates (length mtheta+1) + - **Geometric quantities (rzphi, 4 interpolants):** 2D cubic interpolants for flux-coordinate mapping with periodic BC in theta. @@ -865,6 +885,7 @@ This object provides a complete representation of the processed plasma equilibri + `rzphi_offset::CubicInterpolantND`: η/(2π) - θₙₑw (angle offset) + `rzphi_nu::CubicInterpolantND`: ν in ϕ = 2πζ + ν(ψ, θ) + `rzphi_jac::CubicInterpolantND`: Jacobian + - **Physics quantities (eqfun, 3 interpolants):** 2D cubic interpolants storing local physics and geometric quantities. @@ -873,9 +894,13 @@ This object provides a complete representation of the processed plasma equilibri + `eqfun_B::CubicInterpolantND`: Total magnetic field strength [T] + `eqfun_metric1::CubicInterpolantND`: (e₁⋅e₂ + q⋅e₃⋅e₁)/(J⋅B²) + `eqfun_metric2::CubicInterpolantND`: (e₂⋅e₃ + q⋅e₃⋅e₃)/(J⋅B²) + - `ro::Float64`: R-coordinate of the magnetic axis [m] + - `zo::Float64`: Z-coordinate of the magnetic axis [m] + - `psio::Float64`: Total flux difference |Ψ_axis - Ψ_boundary| [Weber/radian] + - `ingest::EquilibriumIngest`: raw arrays forwarded from the equilibrium input for the `gpec.h5` rerun snapshot — a [`DirectIngest`](@ref)/[`InverseIngest`](@ref) for file-based equilibria, or `nothing` for analytic ones (regenerated from their TOML section on replay) diff --git a/src/Equilibrium/GeometryProfiles.jl b/src/Equilibrium/GeometryProfiles.jl index a9596c308..9b414cf83 100644 --- a/src/Equilibrium/GeometryProfiles.jl +++ b/src/Equilibrium/GeometryProfiles.jl @@ -27,7 +27,7 @@ function compute_geometry_profiles( rzphi_rsquared::FastInterpolations.CubicInterpolantND, rzphi_offset::FastInterpolations.CubicInterpolantND, rzphi_jac::FastInterpolations.CubicInterpolantND, - ro::Float64, + ro::Float64 ) npsi = length(rzphi_xs) mthsurf = length(rzphi_ys) - 1 # skip the periodic duplicate at θ = 1 @@ -78,6 +78,6 @@ function compute_geometry_profiles(pe::PlasmaEquilibrium) return compute_geometry_profiles( pe.rzphi_xs, pe.rzphi_ys, pe.rzphi_rsquared, pe.rzphi_offset, pe.rzphi_jac, - pe.ro, + pe.ro ) end diff --git a/src/Equilibrium/ReadEquilibrium.jl b/src/Equilibrium/ReadEquilibrium.jl index 8cc221b7a..068814505 100644 --- a/src/Equilibrium/ReadEquilibrium.jl +++ b/src/Equilibrium/ReadEquilibrium.jl @@ -432,15 +432,17 @@ Load an equilibrium from an IMAS data dictionary and return a `DirectRunInput`. The `dd.equilibrium.time_slice[]` is used (active time slice). Poloidal flux is converted from the IMAS COCOS convention (set by `config.imas_cocos`) to the internal COCOS 2 convention: + - `imas_cocos = 11` (default, IMAS standard): divide ψ by 2π - `imas_cocos = 2` (GPEC internal): no conversion ## Arguments -- `config`: `EquilibriumConfig` with `eq_type = "imas"` and `imas_cocos` set. -- `dd`: populated `IMASdd.dd` with `dd.equilibrium.time_slice[]` containing: - - `global_quantities.psi_axis`, `global_quantities.psi_boundary` - - `profiles_1d.psi`, `profiles_1d.f`, `profiles_1d.pressure`, `profiles_1d.q` - - `profiles_2d[1].grid.dim1` (R), `profiles_2d[1].grid.dim2` (Z), `profiles_2d[1].psi` + + - `config`: `EquilibriumConfig` with `eq_type = "imas"` and `imas_cocos` set. + - `dd`: populated `IMASdd.dd` with `dd.equilibrium.time_slice[]` containing: + + `global_quantities.psi_axis`, `global_quantities.psi_boundary` + + `profiles_1d.psi`, `profiles_1d.f`, `profiles_1d.pressure`, `profiles_1d.q` + + `profiles_2d[1].grid.dim1` (R), `profiles_2d[1].grid.dim2` (Z), `profiles_2d[1].psi` """ function read_imas(config::EquilibriumConfig, dd) @info "Processing IMAS equilibrium at global_time = $(dd.global_time) s" diff --git a/src/ForceFreeStates/EulerLagrange.jl b/src/ForceFreeStates/EulerLagrange.jl index 88c1d9e4a..3ed691261 100644 --- a/src/ForceFreeStates/EulerLagrange.jl +++ b/src/ForceFreeStates/EulerLagrange.jl @@ -37,9 +37,9 @@ end # at the interval endpoints. Coefficients are ported from STRIDE's ode_itime cost model # (Fortran reference) and unchanged here. Tune only after re-fitting against a per-chunk # step-count sweep; touching these affects parallel-chunk load balancing. -const ODE_COST_AXIS = (a = 39695.0, b = 212830.0) -const ODE_COST_RAT = (a = 17147.0, b = 470710.0) -const ODE_COST_EDGE = (a = 1646.0, b = 4683.0) +const ODE_COST_AXIS = (a=39695.0, b=212830.0) +const ODE_COST_RAT = (a=17147.0, b=470710.0) +const ODE_COST_EDGE = (a=1646.0, b=4683.0) """ ode_itime_cost(psi1, psi2, intr) -> Float64 @@ -72,7 +72,7 @@ never from `Threads.nthreads()` — so the chunk list, and hence every Riccati o identical whatever thread count `julia -t` provides. Each split finds the equal-cost midpoint ψ_mid via bisection: - ode_itime_cost(psi_start, psi_mid) ≈ ode_itime_cost(psi_start, psi_end) / 2 +ode_itime_cost(psi_start, psi_mid) ≈ ode_itime_cost(psi_start, psi_end) / 2 Sub-chunks inherit `needs_crossing=false` and `ising=0`. Only the LAST sub-chunk of each original chunk retains `needs_crossing=true` and the original `ising`, so the @@ -131,10 +131,10 @@ function balance_integration_chunks(chunks::Vector{IntegrationChunk}, ctrl::Forc psi_mid = (lo + hi) / 2.0 left = IntegrationChunk(; psi_start=chunk.psi_start, psi_end=psi_mid, - needs_crossing=false, ising=0, direction=1) + needs_crossing=false, ising=0, direction=1) right = IntegrationChunk(; psi_start=psi_mid, psi_end=chunk.psi_end, - needs_crossing=chunk.needs_crossing, ising=chunk.ising, - direction=chunk.direction) + needs_crossing=chunk.needs_crossing, ising=chunk.ising, + direction=chunk.direction) splice!(result, best_idx, [left, right]) end @@ -284,20 +284,20 @@ is identified by dominant |U₁| component, giving the physically correct consta Frobenius solution and avoiding the spurious logarithmic irregularity. """ function compute_axis_init(ffit::FourFitVars, profiles::Equilibrium.ProfileSplines, - intr::ForceFreeStatesInternal, psi_low::Float64) - N = intr.numpert_total + intr::ForceFreeStatesInternal, psi_low::Float64) + N = intr.numpert_total hint = Ref(1) # Evaluate stability matrices at psi_low F_lower = zeros(ComplexF64, N, N) - kmat = zeros(ComplexF64, N, N) - gmat = zeros(ComplexF64, N, N) + kmat = zeros(ComplexF64, N, N) + gmat = zeros(ComplexF64, N, N) ffit.fmats_lower(vec(F_lower), psi_low; hint=hint) - ffit.kmats(vec(kmat), psi_low; hint=hint) - ffit.gmats(vec(gmat), psi_low; hint=hint) + ffit.kmats(vec(kmat), psi_low; hint=hint) + ffit.gmats(vec(gmat), psi_low; hint=hint) # singfac[j] = 1 / (m_j − n_j · q) for each mode j - q0 = profiles.q_spline(psi_low; hint=hint) + q0 = profiles.q_spline(psi_low; hint=hint) singfac = vec(1.0 ./ ((intr.mlow:intr.mhigh) .- q0 .* (intr.nlow:intr.nhigh)')) # F̄⁻¹ = (F_lower · F_lower')⁻¹ via the Cholesky factor @@ -311,15 +311,15 @@ function compute_axis_init(ffit::FourFitVars, profiles::Equilibrium.ProfileSplin for j in 1:N sf = singfac[j] fi = Finv[j, j] - k = kmat[j, j] + k = kmat[j, j] kd = conj(k) # K̄†[j,j] - g = gmat[j, j] + g = gmat[j, j] # 2×2 ODE matrix block for mode j [Glasser 2016 Eq. 22-24, diagonal approximation] m11 = -sf * fi * k - m12 = sf^2 * fi - m21 = g - kd * fi * k - m22 = sf * kd * fi + m12 = sf^2 * fi + m21 = g - kd * fi * k + m22 = sf * kd * fi # Frobenius matrix A₀_j = ψ_low · M_j [Glasser 2016 Eq. 51] #! format: off @@ -346,7 +346,7 @@ function compute_axis_init(ffit::FourFitVars, profiles::Equilibrium.ProfileSplin if abs(v2) > Base.sqrt(Base.eps(Float64)) * abs(v1) U1_init[j, j] = v1 / v2 else - U1_init[j, j] = one(ComplexF64) + U1_init[j, j] = one(ComplexF64) U2_init[j, j] = zero(ComplexF64) end end @@ -365,7 +365,7 @@ Formerly `ode_axis_init!`. This now only initializes `psifac`, `ising_start`, an Move ising_start logic to chunk_el_integration_bounds? """ function initialize_el_at_axis!(odet::OdeState, ctrl::ForceFreeStatesControl, ffit::FourFitVars, - profiles::Equilibrium.ProfileSplines, intr::ForceFreeStatesInternal) + profiles::Equilibrium.ProfileSplines, intr::ForceFreeStatesInternal) # Default psifac to minimum equilibrium psi value odet.psifac = profiles.xs[1] @@ -542,7 +542,7 @@ function chunk_el_integration_bounds(odet::OdeState, ctrl::ForceFreeStatesContro psi_end=psi_end, needs_crossing=true, ising=ising_current, - direction = bidirectional ? -1 : 1 + direction=bidirectional ? -1 : 1 )) # After crossing, we jump to the other side of the singular surface @@ -975,7 +975,7 @@ function transform_u!(odet::OdeState, intr::ForceFreeStatesInternal) temp[ksol, jsol] = odet.fixfac[ksol, jsol, ifix] end end - mul!(gauss_buffer, view(gauss,:,:,ifix), temp) + mul!(gauss_buffer, view(gauss, :, :, ifix), temp) gauss[:, :, ifix] .= gauss_buffer end # Account for zeroed indices at singular surfaces in `ode_ideal_cross` @@ -992,7 +992,7 @@ function transform_u!(odet::OdeState, intr::ForceFreeStatesInternal) # and mfix + 1 is the for the region after the last fixup and before the edge transforms[:, :, end] .= identity for ifix in odet.ifix:-1:1 - mul!(view(transforms,:,:,ifix), view(gauss,:,:,ifix), view(transforms,:,:,(ifix+1))) + mul!(view(transforms, :, :, ifix), view(gauss, :, :, ifix), view(transforms, :, :, (ifix+1))) end # Now that we have the transform matrices, we can apply them to the solution vectors diff --git a/src/ForceFreeStates/Galerkin/GalerkinAssembly.jl b/src/ForceFreeStates/Galerkin/GalerkinAssembly.jl index 3032e6ef7..787305d96 100644 --- a/src/ForceFreeStates/Galerkin/GalerkinAssembly.jl +++ b/src/ForceFreeStates/Galerkin/GalerkinAssembly.jl @@ -119,11 +119,12 @@ function gal_gauss_quad!(cell::GalCell, ffit::FourFitVars, profiles, intr::Force pb = swap_edge ? (pbt[1], pbt[2], pbt[4], pbt[3]) : pbt qb = swap_edge ? (qbt[1], qbt[2], qbt[4], qbt[3]) : qbt for ip in 0:np, ipert in 1:N, jp in 0:np, jpert in 1:N - cell.mat[ipert, jpert, ip+1, jp+1] += w * ( - F[ipert, jpert] * qb[ip+1] * qb[jp+1] + - K[ipert, jpert] * qb[ip+1] * pb[jp+1] + - conj(K[jpert, ipert]) * pb[ip+1] * qb[jp+1] + - G[ipert, jpert] * pb[ip+1] * pb[jp+1]) + cell.mat[ipert, jpert, ip+1, jp+1] += + w * ( + F[ipert, jpert] * qb[ip+1] * qb[jp+1] + + K[ipert, jpert] * qb[ip+1] * pb[jp+1] + + conj(K[jpert, ipert]) * pb[ip+1] * qb[jp+1] + + G[ipert, jpert] * pb[ip+1] * pb[jp+1]) end end return cell @@ -345,8 +346,8 @@ function gal_resonant!(cell::GalCell, ising::Int, ffit::FourFitVars, profiles, if verbose @info " resonant jsing=$jsing side=$(cell.extra) qerr=$(qerr) res1=$(raw[1]) res2=$(raw[2])" end - hbig = reshape(@view(raw[3:2+N*(np+1)]), N, np + 1) - hsmall = reshape(@view(raw[3+N*(np+1):end]), N, np + 1) + hbig = reshape(@view(raw[3:(2+N*(np+1))]), N, np + 1) + hsmall = reshape(@view(raw[(3+N*(np+1)):end]), N, np + 1) # Apply the right-side negation and the gal_make_arrays signs (gal.f gal_make_arrays) cell.erhs = -sgn_u * raw[1] @@ -449,7 +450,7 @@ including its full three-way edge branch (rpec count `ncoil = ws.nsol - 2*msing` - free boundary (`wv_edge !== nothing`): add the vacuum block `wvac·psio²` at the edge value DOF (gal.f). - fixed boundary (else): identity edge (gal.f). -`wv_edge` is `nothing` for the rpec and fixed cases. + `wv_edge` is `nothing` for the rpec and fixed cases. """ function gal_set_boundary!(ws::GalWorkspace, mpert::Int, wv_edge::Union{Nothing,Matrix{ComplexF64}}) chol = ws.solver == "cholesky" @@ -474,7 +475,7 @@ function gal_set_boundary!(ws::GalWorkspace, mpert::Int, wv_edge::Union{Nothing, cell.mat[idx, idx, 4, 4] = 1 end for ipert in 1:mpert - ws.rhs[cell.map[ipert, 4], 2 * msing + ipert] = 1 + ws.rhs[cell.map[ipert, 4], 2*msing+ipert] = 1 end elseif wv_edge !== nothing # free boundary: vacuum block wvac·psio² (gal.f) diff --git a/src/ForceFreeStates/Galerkin/GalerkinGrid.jl b/src/ForceFreeStates/Galerkin/GalerkinGrid.jl index 497e26e70..49b369fba 100644 --- a/src/ForceFreeStates/Galerkin/GalerkinGrid.jl +++ b/src/ForceFreeStates/Galerkin/GalerkinGrid.jl @@ -20,7 +20,7 @@ function gal_pack(nx::Int, pfac::Float64, side::String) elseif side == "right" xi = collect(0:2nx) ./ (2nx) elseif side == "both" - xi = collect(-nx:nx) ./ nx + xi = collect((-nx):nx) ./ nx else error("gal_pack: unrecognized side = $side") end diff --git a/src/ForceFreeStates/Galerkin/GalerkinSolve.jl b/src/ForceFreeStates/Galerkin/GalerkinSolve.jl index 66dddd893..3b659e2da 100644 --- a/src/ForceFreeStates/Galerkin/GalerkinSolve.jl +++ b/src/ForceFreeStates/Galerkin/GalerkinSolve.jl @@ -39,7 +39,9 @@ function gal_make_arrays!(ws::GalWorkspace, ctrl::ForceFreeStatesControl, equil, return ws end -"""Empty `GalerkinResult` for a domain with no resonant surfaces.""" +""" +Empty `GalerkinResult` for a domain with no resonant surfaces. +""" function empty_galerkin_result() return GalerkinResult(0, Float64[], Float64[], Int[], Int[], Float64[], ComplexF64[], nothing, nothing) end diff --git a/src/ForceFreeStates/Resist.jl b/src/ForceFreeStates/Resist.jl index 3c436daa2..066d10179 100644 --- a/src/ForceFreeStates/Resist.jl +++ b/src/ForceFreeStates/Resist.jl @@ -33,11 +33,13 @@ coefficients E, F, G, H, K, M, the local time scales τ_A (`taua`), τ_R (`taur` by total volume), and the surface index `ising`. # Required keyword arguments + - `eta::Real` — plasma resistivity η at this surface [Ω·m] - `rho::Real` — mass density ρ at this surface [kg/m³] - `gamma::Real` — ratio of specific heats (enters G; physical thermodynamic value, e.g. 5/3) # Physics + The six flux-surface averages (Fortran `avg(1:6)`) are `⟨B²/|∇ψ|²⟩, ⟨1/|∇ψ|²⟩, ⟨1/B²⟩, ⟨1/(B²|∇ψ|²)⟩, ⟨B²⟩, ⟨|∇ψ|²/B²⟩`, each weighted by `J/V′` and integrated over θ ∈ [0,1) — exactly the resist.f integrands. The timescales are @@ -150,10 +152,10 @@ function resonant_match_rpec(delta_out_raw::AbstractMatrix, delta_coil_raw::Abst size(delta_coil_raw, 1) == 2msing || error("delta_coil_raw rows $(size(delta_coil_raw,1)) != 2msing") if ctrl.gal_ideal_flag # ideal limit: no inner layer, no reconnection - return ResonantMatchResult(zeros(ComplexF64,2msing,ncoil), zeros(ComplexF64,2msing,ncoil), - zeros(ComplexF64,msing,2), zeros(ComplexF64,msing), Matrix{ComplexF64}(delta_coil_raw), empty_bpen, 0.0) + return ResonantMatchResult(zeros(ComplexF64, 2msing, ncoil), zeros(ComplexF64, 2msing, ncoil), + zeros(ComplexF64, msing, 2), zeros(ComplexF64, msing), Matrix{ComplexF64}(delta_coil_raw), empty_bpen, 0.0) end - for (nm,v) in (("gal_eta",ctrl.gal_eta),("gal_rho",ctrl.gal_rho),("gal_rotation",ctrl.gal_rotation)) + for (nm, v) in (("gal_eta", ctrl.gal_eta), ("gal_rho", ctrl.gal_rho), ("gal_rotation", ctrl.gal_rotation)) length(v) == msing || error("$nm length $(length(v)) != msing $msing") end @@ -169,37 +171,47 @@ function resonant_match_rpec(delta_out_raw::AbstractMatrix, delta_coil_raw::Abst rpec_eig[i] = γ inner = InnerLayer.solve_inner_profile(InnerLayer.GGJModel(; solver=:galerkin), params, γ; xfac=ctrl.gal_inner_xfac, nx=ctrl.gal_inner_nx, nq=ctrl.gal_inner_nq, cutoff=ctrl.gal_inner_cutoff, kmax=ctrl.gal_inner_kmax) - deltar[i,1] = inner.Δ[1]; deltar[i,2] = inner.Δ[2] + deltar[i, 1] = inner.Δ[1] + deltar[i, 2] = inner.Δ[2] scale = -2π * chi1 * im * nn * sings[i].q1 * inner.dψdx # b_m = −2πi·χ₁·n·q′·dψdx·rescale·Ψ (GalerkinMatch.jl) - pen[i,1] = scale * inner.Ψ[1,1] * inner.rescale # parity 1 (Ψ(0)≠0) - pen[i,2] = scale * inner.Ψ[1,2] * inner.rescale # parity 2 (Ψ(0)=0 ⇒ ~0) + pen[i, 1] = scale * inner.Ψ[1, 1] * inner.rescale # parity 1 (Ψ(0)≠0) + pen[i, 2] = scale * inner.Ψ[1, 2] * inner.rescale # parity 2 (Ψ(0)=0 ⇒ ~0) end - mat = zeros(ComplexF64, 4msing, 4msing) + mat = zeros(ComplexF64, 4msing, 4msing) rmat = zeros(ComplexF64, 4msing, ncoil) - @views mat[2msing+1:4msing, 1:2msing] .= transpose(delta_out_raw) - @views rmat[2msing+1:4msing, :] .= .-delta_coil_raw + @views mat[(2msing+1):4msing, 1:2msing] .= transpose(delta_out_raw) + @views rmat[(2msing+1):4msing, :] .= .-delta_coil_raw for i in 1:msing - a=2i-1; b=2i; c=a+2msing; d=b+2msing - d1=deltar[i,1]; d2=deltar[i,2] - mat[a,a]=1; mat[b,b]=1 - mat[a,c]=-1; mat[a,d]=1 - mat[b,c]=-1; mat[b,d]=-1 - mat[c,c]=-d1; mat[c,d]=d2 - mat[d,c]=-d1; mat[d,d]=-d2 + a=2i-1 + b=2i + c=a+2msing + d=b+2msing + d1=deltar[i, 1] + d2=deltar[i, 2] + mat[a, a]=1 + mat[b, b]=1 + mat[a, c]=-1 + mat[a, d]=1 + mat[b, c]=-1 + mat[b, d]=-1 + mat[c, c]=-d1 + mat[c, d]=d2 + mat[d, c]=-d1 + mat[d, d]=-d2 end cof = mat \ rmat residual = norm(mat*cof - rmat) / max(norm(rmat), 1e-300) cout = cof[1:2msing, :] - cin = cof[2msing+1:4msing, :] - + cin = cof[(2msing+1):4msing, :] + reconnected_flux = delta_coil_raw .+ transpose(delta_out_raw)*cout # Inner-layer penetrated (reconnected) resonant field per surface — ONE quantity per surface, read off # the inner solution at the layer center (match.f intotsol_b; GalerkinMatch.jl): bpen[i,j] = pen₁(i)·cin[2i,j] + pen₂(i)·cin[2i-1,j]. bpen = zeros(ComplexF64, msing, ncoil) for i in 1:msing, j in 1:ncoil - bpen[i,j] = pen[i,1]*cin[2i,j] + pen[i,2]*cin[2i-1,j] + bpen[i, j] = pen[i, 1]*cin[2i, j] + pen[i, 2]*cin[2i-1, j] end return ResonantMatchResult(cout, cin, deltar, rpec_eig, reconnected_flux, bpen, residual) -end \ No newline at end of file +end diff --git a/src/ForceFreeStates/ResistEval.jl b/src/ForceFreeStates/ResistEval.jl index 04953b6c0..0f472bb38 100644 --- a/src/ForceFreeStates/ResistEval.jl +++ b/src/ForceFreeStates/ResistEval.jl @@ -33,23 +33,23 @@ Per-singular-surface Glasser-Greene-Johnson geometric coefficients and supporting flux-surface averages. -| field | meaning | -|-------------|------------------------------------------------------| -| `E`, `F` | Glasser interchange parameters (enter `D_I = E+F+H-¼`) | -| `G` | Coupling coefficient (curvature × pressure gradient) | -| `H` | Pfirsch-Schlüter coefficient | -| `K` | Glasser parameter | -| `M` | Mass factor | -| `avg_bsq_over_dpsisq` | ⟨B²/|∇ψ|²⟩ — needed for τ_R | -| `avg_bsq` | ⟨B²⟩ — needed for τ_R | -| `avg_B` | ⟨B⟩ — needed for Lin-Liu-Miller f_t | -| `B_max`, `B_min` | θ-extrema of B on the surface [T] | -| `f_trap` | Lin-Liu & Miller 1995 trapped-particle fraction | -| `R_major` | flux-surface-averaged major radius ⟨R⟩ [m] | -| `eps_local` | (R_max − R_min)/2 / R_major — local inverse aspect ratio | -| `p_local` | Plasma pressure at this surface [Pa] | -| `p1_local` | dp/dψ at this surface | -| `v1_local` | dV/dψ at this surface | +| field | meaning | +|:--------------------- |:-------------------------------------------------------- | +| `E`, `F` | Glasser interchange parameters (enter `D_I = E+F+H-¼`) | +| `G` | Coupling coefficient (curvature × pressure gradient) | +| `H` | Pfirsch-Schlüter coefficient | +| `K` | Glasser parameter | +| `M` | Mass factor | +| `avg_bsq_over_dpsisq` | ⟨B²/ | +| `avg_bsq` | ⟨B²⟩ — needed for τ_R | +| `avg_B` | ⟨B⟩ — needed for Lin-Liu-Miller f_t | +| `B_max`, `B_min` | θ-extrema of B on the surface [T] | +| `f_trap` | Lin-Liu & Miller 1995 trapped-particle fraction | +| `R_major` | flux-surface-averaged major radius ⟨R⟩ [m] | +| `eps_local` | (R_max − R_min)/2 / R_major — local inverse aspect ratio | +| `p_local` | Plasma pressure at this surface [Pa] | +| `p1_local` | dp/dψ at this surface | +| `v1_local` | dV/dψ at this surface | `H` here is identical to the `H` reported by `mercier_scan!` and stored in `LocalStability/h` — the GGJ routine recomputes it for convenience. @@ -99,6 +99,7 @@ standard GGJ formulas. - `gamma` — adiabatic index (default 5/3) !!! note "Contract" + `psifac` must be a genuine interior rational surface (`0 < ψ < 1`) with nonzero `q1`, `p1 = dp/dψ`, and `p`. The GGJ combination divides by these and by `|∇ψ|²` (which → 0 at the axis), so calling on the magnetic axis, @@ -107,47 +108,47 @@ standard GGJ formulas. rationals. """ function resist_geometry(equil::Equilibrium.PlasmaEquilibrium, - psifac::Real, q1::Real; gamma::Real=5/3) + psifac::Real, q1::Real; gamma::Real=5/3) profiles = equil.profiles - twopi = 2π - chi1 = twopi * equil.psio - psi_f = Float64(psifac) + twopi = 2π + chi1 = twopi * equil.psio + psi_f = Float64(psifac) # Surface-profile quantities (evaluate via the existing splines) twopif = profiles.F_spline(psi_f) - p = profiles.P_spline(psi_f) - p1 = profiles.P_deriv(psi_f) - v1 = profiles.dVdpsi_spline(psi_f) - v2 = profiles.dVdpsi_deriv(psi_f) - q = profiles.q_spline(psi_f) + p = profiles.P_spline(psi_f) + p1 = profiles.P_deriv(psi_f) + v1 = profiles.dVdpsi_spline(psi_f) + v2 = profiles.dVdpsi_deriv(psi_f) + q = profiles.q_spline(psi_f) # Build the 6 GGJ θ-integrands plus a 7th (B) for the neoclassical # resistivity f_t calculation, and accumulate running extrema of # (B, R) for Lin-Liu-Miller f_t and the local ε. ntheta = length(equil.rzphi_ys) - ff = zeros(Float64, ntheta, 7) - B_max = -Inf - B_min = Inf - R_max = -Inf - R_min = Inf + ff = zeros(Float64, ntheta, 7) + B_max = -Inf + B_min = Inf + R_max = -Inf + R_min = Inf for itheta in 1:ntheta theta = equil.rzphi_ys[itheta] - f1 = equil.rzphi_rsquared((psi_f, theta)) - f2 = equil.rzphi_offset((psi_f, theta)) + f1 = equil.rzphi_rsquared((psi_f, theta)) + f2 = equil.rzphi_offset((psi_f, theta)) jac = equil.rzphi_jac((psi_f, theta)) fy1 = FastInterpolations.deriv_view(equil.rzphi_rsquared, (0, 1))((psi_f, theta)) - fy2 = FastInterpolations.deriv_view(equil.rzphi_offset, (0, 1))((psi_f, theta)) - fy3 = FastInterpolations.deriv_view(equil.rzphi_nu, (0, 1))((psi_f, theta)) + fy2 = FastInterpolations.deriv_view(equil.rzphi_offset, (0, 1))((psi_f, theta)) + fy3 = FastInterpolations.deriv_view(equil.rzphi_nu, (0, 1))((psi_f, theta)) rfac = sqrt(f1) - eta = twopi * (theta + f2) - r = equil.ro + rfac * cos(eta) + eta = twopi * (theta + f2) + r = equil.ro + rfac * cos(eta) v21 = fy1 / (2 * rfac * jac) v22 = (1 + fy2) * twopi * rfac / jac v23 = fy3 * r / jac v33 = twopi * r / jac - bsq = chi1^2 * (v21^2 + v22^2 + (v23 + q*v33)^2) + bsq = chi1^2 * (v21^2 + v22^2 + (v23 + q*v33)^2) dpsisq = (twopi * r)^2 * (v21^2 + v22^2) B_here = sqrt(bsq) @@ -180,7 +181,7 @@ function resist_geometry(equil::Equilibrium.PlasmaEquilibrium, (twopif * q1 * chi1 / avg[5] - v2) F_coef = (p1 * v1 / (q1 * chi1^2))^2 * (avg[1] * avg[3] + (twopif / chi1)^2 * - (avg[1] * avg[4] - avg[2]^2)) + (avg[1] * avg[4] - avg[2]^2)) H_coef = twopif * p1 * v1 / (q1 * chi1^3) * (avg[2] - avg[1] / avg[5]) M_coef = avg[1] * (avg[6] + (twopif / chi1)^2 * (avg[3] - 1.0 / avg[5])) @@ -192,7 +193,7 @@ function resist_geometry(equil::Equilibrium.PlasmaEquilibrium, E_coef, F_coef, G_coef, H_coef, K_coef, M_coef, avg[1], avg[5], avg_B, B_max, B_min, f_trap, R_major, eps_local, - p, p1, v1, + p, p1, v1 ) end @@ -204,8 +205,8 @@ Populate `sing.restype` for every `SingType` in `intr.sing` using filled. """ function resist_eval_all!(intr::ForceFreeStatesInternal, - equil::Equilibrium.PlasmaEquilibrium; - gamma::Real=5/3) + equil::Equilibrium.PlasmaEquilibrium; + gamma::Real=5/3) for sing in intr.sing sing.restype === nothing || continue sing.restype = resist_geometry(equil, sing.psifac, sing.q1; gamma=gamma) diff --git a/src/ForceFreeStates/Riccati.jl b/src/ForceFreeStates/Riccati.jl index c1710cc12..7f9c8ee3a 100644 --- a/src/ForceFreeStates/Riccati.jl +++ b/src/ForceFreeStates/Riccati.jl @@ -97,7 +97,7 @@ This is compatible with downstream code (which uses U₁/U₂ ratio): # length chunks; the absolute floor catches short chunks where 5% of the span would be # smaller than the typical ODE step. const SAVE_NEAR_END_FRAC = 0.05 -const SAVE_NEAR_END_PSI = 1e-4 +const SAVE_NEAR_END_PSI = 1e-4 """ assemble_fm_matrix(propagators, idx_range; condition=false) -> Matrix{ComplexF64} @@ -107,6 +107,7 @@ in order for indices `idx_range`. Returns Φ_end * ... * Φ_start, so that the r maps the IC at the start of `idx_range[1]` to the state at the end of `idx_range[end]`. Each `ChunkPropagator` stores the 2N columns of Φ split into two N×N×2 blocks: + ``` block_upper_ic[:,:,1:2] ↔ Φ[:,1:N] (result from IC=(I,0)) block_lower_ic[:,:,1:2] ↔ Φ[:,N+1:2N] (result from IC=(0,I)) @@ -124,8 +125,8 @@ means only U₂ ICs are needed. Do NOT use for inter-surface segments where both and U₂ components carry physical information. """ function assemble_fm_matrix(propagators::Vector{ChunkPropagator}, idx_range; - condition::Bool=false, - T_init::Union{Nothing,Matrix{ComplexF64}}=nothing) + condition::Bool=false, + T_init::Union{Nothing,Matrix{ComplexF64}}=nothing) # Determine matrix size from T_init if provided (lets us handle empty idx_range and even # an empty propagators list, provided T_init carries the dimension). Otherwise fall back # to the first propagator that actually exists in idx_range, with a final fallback to @@ -167,7 +168,7 @@ After conditioning, only the U₂ columns carry meaningful information; the U₁ """ function condition_propagator!(Phi::Matrix{ComplexF64}, N::Int) # Work on the right half: columns N+1:2N (U₂ initial conditions) - cols = view(Phi, :, N+1:2N) + cols = view(Phi, :, (N+1):2N) # Sort columns by norm of the U₁ (upper N) block — largest first norms = [norm(view(cols, 1:N, k)) for k in 1:N] @@ -217,6 +218,7 @@ Compute the inter-surface tearing stability matrix (msing × msing) using the STRIDE global BVP formulation [Glasser 2018 Phys. Plasmas 25, 032501, Sec. III.B]. The BVP encodes the full plasma response with unknowns at each surface boundary: + ``` x_axis (N): free IC parameters at the axis (U₁ = 0 regular solutions) x_left[j] (2N): state at left inner-layer boundary of surface j @@ -229,9 +231,11 @@ The BVP encodes the full plasma response with unknowns at each surface boundary: When `wv` is provided (the vacuum response matrix, singfac-scaled), the edge BC follows the Fortran STRIDE convention: + ``` U₁ = c, U₂ = -wv·ψ₀²·c ``` + which is the free-boundary condition `wp + wv = 0` at the edge. When `wv` is `nothing`, a conducting wall BC (`U₁ = 0`) is used. @@ -248,9 +252,11 @@ keeps the BVP matrix full-rank and well-conditioned. The raw BVP solution is a 2·msing × 2·msing matrix `dp` with left/right sub-indices at each surface. The PEST3-convention Δ' matrix is the linear combination [Chance, PPPL-2527]: + ``` deltap(i,j) = dp(2i,2j) - dp(2i,2j-1) - dp(2i-1,2j) + dp(2i-1,2j-1) ``` + stored in `intr.delta_prime_matrix` (msing × msing). ## Limitations @@ -275,13 +281,13 @@ function compute_delta_prime_matrix!( intr::ForceFreeStatesInternal, propagators::Vector{ChunkPropagator}, chunks::Vector{IntegrationChunk}; - wv::Union{Nothing,Matrix{ComplexF64}} = nothing, - psio::Float64 = 0.0, - debug::Bool = false, - S_at_surface_left::Union{Nothing,Vector{Matrix{ComplexF64}}} = nothing, - ctrl::Union{Nothing,ForceFreeStatesControl} = nothing, - equil::Union{Nothing,Equilibrium.PlasmaEquilibrium} = nothing, - ffit::Union{Nothing,FourFitVars} = nothing + wv::Union{Nothing,Matrix{ComplexF64}}=nothing, + psio::Float64=0.0, + debug::Bool=false, + S_at_surface_left::Union{Nothing,Vector{Matrix{ComplexF64}}}=nothing, + ctrl::Union{Nothing,ForceFreeStatesControl}=nothing, + equil::Union{Nothing,Equilibrium.PlasmaEquilibrium}=nothing, + ffit::Union{Nothing,FourFitVars}=nothing ) intr.msing == 0 && return _has_unsupported_multi_resonance(intr) && return @@ -301,8 +307,10 @@ function compute_delta_prime_matrix!( if !use_S_axis for ic in i_crossings chunks[ic].direction == 1 || - error("compute_delta_prime_matrix!: FM-axis fallback (use_S_axis=false) requires forward crossing chunks; " * - "chunk $ic has direction=$(chunks[ic].direction). Either provide S_at_surface_left or use bidirectional=false.") + error( + "compute_delta_prime_matrix!: FM-axis fallback (use_S_axis=false) requires forward crossing chunks; " * + "chunk $ic has direction=$(chunks[ic].direction). Either provide S_at_surface_left or use bidirectional=false." + ) end end @@ -315,15 +323,15 @@ function compute_delta_prime_matrix!( _build_asymptotic_basis_matrices(sing, has_ua, N, msing) debug && _log_bvp_setup(chunks, sing, S_at_surface_left, use_S_axis, has_ua, - Phi_L_mats, Phi_R_mats, Phi_R_halves, ipert_all, wv, psio, N, msing) + Phi_L_mats, Phi_R_mats, Phi_R_halves, ipert_all, wv, psio, N, msing) if use_S_axis uShootR, uShootL, uAxis = _build_S_axis_shooting_propagators( propagators, chunks, i_crossings, sing, msing, N, T_left_mats, T_right_mats, has_ua, ctrl, equil, ffit, intr, debug) debug && _log_S_axis_shooting_propagators(uShootR, uShootL, uAxis, - S_at_surface_left, T_left_mats, - ipert_all, has_ua, msing, N) + S_at_surface_left, T_left_mats, + ipert_all, has_ua, msing, N) M, nMat, col_edge = _assemble_bvp_S_axis( uShootR, uShootL, uAxis, ipert_all, msing, N, wv, psio) else @@ -350,13 +358,13 @@ function compute_delta_prime_matrix!( # The raw matrix is consumed by `pest3_decompose` to recover (A', B', Γ', Δ') for the full # det(D' − D(γ)) = 0 eigenvalue problem; see ForceFreeStatesStructs.jl docstring. intr.delta_prime_matrix = deltap - intr.delta_prime_raw = dp_raw_persisted + intr.delta_prime_raw = dp_raw_persisted end # Column index helpers for the BVP matrix. j is the 1-based singular-surface index, # N is numpert_total. Layout: c_axis(N), c_left[1](2N), c_right[1](2N), ..., c_edge(N). -_col_left(j::Int, N::Int) = (N + 4N*(j-1) + 1):(N + 4N*(j-1) + 2N) -_col_right(j::Int, N::Int) = (N + 4N*(j-1) + 2N + 1):(N + 4N*j) +_col_left(j::Int, N::Int) = (N+4N*(j-1)+1):(N+4N*(j-1)+2N) +_col_right(j::Int, N::Int) = (N+4N*(j-1)+2N+1):(N+4N*j) # Multi-resonance surfaces (one q value satisfying multiple (m,n) tuples in a multi-n run) # are not yet handled by the inter-surface BVP. Returns true if any surface has >1 modes; @@ -395,28 +403,28 @@ end # Midpoint splitting halves each inter-surface span's condition number — STRIDE's trick: # cond(full) = 10¹⁵ → cond(half) ≈ 10⁷·⁵, an 8-digit accuracy gain. function _assemble_segment_propagators(propagators::Vector{ChunkPropagator}, - chunks::Vector{IntegrationChunk}, - i_crossings::Vector{Int}, msing::Int, N::Int, - use_S_axis::Bool) + chunks::Vector{IntegrationChunk}, + i_crossings::Vector{Int}, msing::Int, N::Int, + use_S_axis::Bool) Phi_L_mats = [assemble_fm_matrix(propagators, i_crossings[j]:i_crossings[j]) for j in 1:msing] Phi_R_mats = Vector{Matrix{ComplexF64}}(undef, msing + 1) if !use_S_axis - Phi_R_mats[1] = assemble_fm_matrix(propagators, 1:i_crossings[1]-1; condition=true) + Phi_R_mats[1] = assemble_fm_matrix(propagators, 1:(i_crossings[1]-1); condition=true) end for j in 2:msing - Phi_R_mats[j] = assemble_fm_matrix(propagators, i_crossings[j-1]+1:i_crossings[j]-1) + Phi_R_mats[j] = assemble_fm_matrix(propagators, (i_crossings[j-1]+1):(i_crossings[j]-1)) end - Phi_R_mats[msing+1] = assemble_fm_matrix(propagators, i_crossings[msing]+1:length(chunks)) + Phi_R_mats[msing+1] = assemble_fm_matrix(propagators, (i_crossings[msing]+1):length(chunks)) Phi_R_halves = Vector{Tuple{Matrix{ComplexF64},Matrix{ComplexF64}}}(undef, msing - 1) - for j in 1:msing-1 + for j in 1:(msing-1) chunk_start = i_crossings[j] + 1 - chunk_end = i_crossings[j+1] - 1 - n_chunks = chunk_end - chunk_start + 1 + chunk_end = i_crossings[j+1] - 1 + n_chunks = chunk_end - chunk_start + 1 if n_chunks >= 2 i_mid = chunk_start + div(n_chunks, 2) - 1 - Phi_left_half = assemble_fm_matrix(propagators, chunk_start:i_mid) - Phi_right_half = assemble_fm_matrix(propagators, i_mid+1:chunk_end) + Phi_left_half = assemble_fm_matrix(propagators, chunk_start:i_mid) + Phi_right_half = assemble_fm_matrix(propagators, (i_mid+1):chunk_end) Phi_R_halves[j] = (Phi_left_half, Phi_right_half) else Phi_R_halves[j] = (Matrix{ComplexF64}(I, 2N, 2N), Phi_R_mats[j+1]) @@ -430,17 +438,17 @@ end # N+1:2N = small solutions (z^{+α}, bounded). Fortran STRIDE bakes T into the shooting # propagators (uFM_sing_init); we multiply T into the BVP propagator blocks at each surface. function _build_asymptotic_basis_matrices(sing::Vector{SingType}, has_ua::Bool, N::Int, msing::Int) - T_left_mats = Vector{Matrix{ComplexF64}}(undef, msing) + T_left_mats = Vector{Matrix{ComplexF64}}(undef, msing) T_right_mats = Vector{Matrix{ComplexF64}}(undef, msing) - T_left_inv = Vector{Matrix{ComplexF64}}(undef, msing) - T_right_inv = Vector{Matrix{ComplexF64}}(undef, msing) + T_left_inv = Vector{Matrix{ComplexF64}}(undef, msing) + T_right_inv = Vector{Matrix{ComplexF64}}(undef, msing) if has_ua for j in 1:msing sp = sing[j] - T_left_mats[j] = [sp.ua_left[:,:,1]; sp.ua_left[:,:,2]] - T_right_mats[j] = [sp.ua_right[:,:,1]; sp.ua_right[:,:,2]] - T_left_inv[j] = inv(T_left_mats[j]) - T_right_inv[j] = inv(T_right_mats[j]) + T_left_mats[j] = [sp.ua_left[:, :, 1]; sp.ua_left[:, :, 2]] + T_right_mats[j] = [sp.ua_right[:, :, 1]; sp.ua_right[:, :, 2]] + T_left_inv[j] = inv(T_left_mats[j]) + T_right_inv[j] = inv(T_right_mats[j]) end end return T_left_mats, T_right_mats, T_left_inv, T_right_inv @@ -471,7 +479,7 @@ function _build_S_axis_shooting_propagators( end if can_reintegrate && !isempty(shoot_range_R) uShootR[j] = integrate_fm_with_ua_ic(chunks, shoot_range_R, sing[j].ua_right, - ctrl, equil, ffit, intr; backward=false, psi_ua=sing[j].psi_ua_right) + ctrl, equil, ffit, intr; backward=false, psi_ua=sing[j].psi_ua_right) else T_init = has_ua ? T_right_mats[j] : nothing uShootR[j] = assemble_fm_matrix(propagators, shoot_range_R; T_init=T_init) @@ -488,7 +496,7 @@ function _build_S_axis_shooting_propagators( end if can_reintegrate && !isempty(shoot_range_L) uShootL[j] = integrate_fm_with_ua_ic(chunks, shoot_range_L, sing[j].ua_left, - ctrl, equil, ffit, intr; backward=true, psi_ua=sing[j].psi_ua_left) + ctrl, equil, ffit, intr; backward=true, psi_ua=sing[j].psi_ua_left) else T_init = has_ua ? T_left_mats[j] : nothing uShootL[j] = assemble_fm_matrix(propagators, shoot_range_L; T_init=T_init) @@ -497,10 +505,10 @@ function _build_S_axis_shooting_propagators( uAxis, i_axis_mid = _build_conditioned_axis_propagator(propagators, i_crossings, N) uShootL[1] = _build_uShootL_first(propagators, chunks, i_crossings, sing, - T_left_mats, has_ua, can_reintegrate, i_axis_mid, - ctrl, equil, ffit, intr, N) + T_left_mats, has_ua, can_reintegrate, i_axis_mid, + ctrl, equil, ffit, intr, N) if debug - shoot_range_L1 = (i_axis_mid + 1):(i_crossings[1] - 1) + shoot_range_L1 = (i_axis_mid+1):(i_crossings[1]-1) @info " Axis propagator: $(i_axis_mid) chunks, cond=$(@sprintf("%.2e", cond(uAxis)))" @info " uShootL[1]: range=$(shoot_range_L1), cond=$(@sprintf("%.2e", cond(uShootL[1])))" end @@ -513,25 +521,25 @@ end # chunk+1 to chunk(i_crossings[j]-1). The ψ midpoint is used (not the chunk-index midpoint) # because chunks near singularities are packed tighter in ψ — Fortran convention. function _midpoint_shoot_range(chunks::Vector{IntegrationChunk}, i_crossings::Vector{Int}, - j::Int, msing::Int; side::Symbol) + j::Int, msing::Int; side::Symbol) if side === :right - j == msing && return (i_crossings[msing] + 1):length(chunks) + j == msing && return (i_crossings[msing]+1):length(chunks) chunk_start = i_crossings[j] + 1 - chunk_end = i_crossings[j+1] - 1 + chunk_end = i_crossings[j+1] - 1 else # :left, j >= 2 chunk_start = i_crossings[j-1] + 1 - chunk_end = i_crossings[j] - 1 + chunk_end = i_crossings[j] - 1 end psi_mid_target = (chunks[chunk_start].psi_start + chunks[chunk_end].psi_end) / 2 i_mid_inter = chunk_start - for ic in chunk_start:chunk_end-1 + for ic in chunk_start:(chunk_end-1) if chunks[ic].psi_end >= psi_mid_target i_mid_inter = ic break end i_mid_inter = ic end - return side === :right ? (chunk_start:i_mid_inter) : ((i_mid_inter + 1):chunk_end) + return side === :right ? (chunk_start:i_mid_inter) : ((i_mid_inter+1):chunk_end) end # Build a well-conditioned axis propagator by forward-propagating [0; I] through the @@ -539,7 +547,7 @@ end # midpoint is placed one chunk before the first surface so that uShootL[1] covers only the # last chunk, keeping it well-conditioned. function _build_conditioned_axis_propagator(propagators::Vector{ChunkPropagator}, - i_crossings::Vector{Int}, N::Int) + i_crossings::Vector{Int}, N::Int) n_pre_cross = i_crossings[1] - 1 i_axis_mid = max(1, n_pre_cross - 1) uAxis = zeros(ComplexF64, 2N, N) @@ -549,9 +557,9 @@ function _build_conditioned_axis_propagator(propagators::Vector{ChunkPropagator} for ic in 1:i_axis_mid prop = propagators[ic] upper_old = uAxis[1:N, :] - lower_old = uAxis[N+1:2N, :] - uAxis[1:N, :] .= prop.block_upper_ic[:,:,1] * upper_old .+ prop.block_lower_ic[:,:,1] * lower_old - uAxis[N+1:2N, :] .= prop.block_upper_ic[:,:,2] * upper_old .+ prop.block_lower_ic[:,:,2] * lower_old + lower_old = uAxis[(N+1):2N, :] + uAxis[1:N, :] .= prop.block_upper_ic[:, :, 1] * upper_old .+ prop.block_lower_ic[:, :, 1] * lower_old + uAxis[(N+1):2N, :] .= prop.block_upper_ic[:, :, 2] * upper_old .+ prop.block_lower_ic[:, :, 2] * lower_old Q, _ = qr(uAxis) uAxis .= Matrix(Q)[:, 1:N] end @@ -565,18 +573,18 @@ end # Falls back to T_left_mats[1] (or identity if no ua) when there's only 1 chunk before the # first crossing. function _build_uShootL_first(propagators::Vector{ChunkPropagator}, - chunks::Vector{IntegrationChunk}, i_crossings::Vector{Int}, - sing::Vector{SingType}, T_left_mats::Vector{Matrix{ComplexF64}}, - has_ua::Bool, can_reintegrate::Bool, i_axis_mid::Int, - ctrl, equil, ffit, intr::ForceFreeStatesInternal, N::Int) - shoot_range_L1 = (i_axis_mid + 1):(i_crossings[1] - 1) + chunks::Vector{IntegrationChunk}, i_crossings::Vector{Int}, + sing::Vector{SingType}, T_left_mats::Vector{Matrix{ComplexF64}}, + has_ua::Bool, can_reintegrate::Bool, i_axis_mid::Int, + ctrl, equil, ffit, intr::ForceFreeStatesInternal, N::Int) + shoot_range_L1 = (i_axis_mid+1):(i_crossings[1]-1) if can_reintegrate && !isempty(shoot_range_L1) return integrate_fm_with_ua_ic(chunks, shoot_range_L1, sing[1].ua_left, - ctrl, equil, ffit, intr; - backward=true, psi_ua=sing[1].psi_ua_left) + ctrl, equil, ffit, intr; + backward=true, psi_ua=sing[1].psi_ua_left) elseif !isempty(shoot_range_L1) return assemble_fm_matrix(propagators, shoot_range_L1; - T_init=has_ua ? T_left_mats[1] : nothing) + T_init=has_ua ? T_left_mats[1] : nothing) else return has_ua ? T_left_mats[1] : Matrix{ComplexF64}(I, 2N, 2N) end @@ -587,19 +595,19 @@ end # the catastrophically ill-conditioned axis FM. Fortran-matched structure with # nMat = (2 + 4·msing)·N. Returns (M, nMat, col_edge). function _assemble_bvp_S_axis(uShootR::Vector{Matrix{ComplexF64}}, - uShootL::Vector{Matrix{ComplexF64}}, - uAxis::Matrix{ComplexF64}, ipert_all::Vector{Int}, - msing::Int, N::Int, - wv::Union{Nothing,Matrix{ComplexF64}}, psio::Float64) + uShootL::Vector{Matrix{ComplexF64}}, + uAxis::Matrix{ComplexF64}, ipert_all::Vector{Int}, + msing::Int, N::Int, + wv::Union{Nothing,Matrix{ComplexF64}}, psio::Float64) # STRIDE global BVP block structure [Glasser-Kolemen 2018 PoP 25, 032501 Eq. 37]. nMat = (2 + 4 * msing) * N col_axis = 1:N - col_edge = (nMat - N + 1):nMat + col_edge = (nMat-N+1):nMat M = zeros(ComplexF64, nMat, nMat) # Axis matching: uShootL[1] · c_left[1] = uAxis · c_axis (2N equations) M[1:2N, _col_left(1, N)] .= uShootL[1] - M[1:2N, col_axis] .= -uAxis + M[1:2N, col_axis] .= -uAxis row_offset = 2N for j in 1:msing @@ -608,24 +616,24 @@ function _assemble_bvp_S_axis(uShootR::Vector{Matrix{ComplexF64}}, for i in 1:2N if i != ipert_j && i != ipert_j + N row_offset += 1 - M[row_offset, _col_left(j, N)[i]] = 1 + M[row_offset, _col_left(j, N)[i]] = 1 M[row_offset, _col_right(j, N)[i]] = -1 end end - junc_rows = (row_offset + 1):(row_offset + 2N) + junc_rows = (row_offset+1):(row_offset+2N) if j < msing # Midpoint matching between consecutive surfaces - M[junc_rows, _col_right(j, N)] .= -uShootR[j] - M[junc_rows, _col_left(j+1, N)] .= uShootL[j+1] + M[junc_rows, _col_right(j, N)] .= -uShootR[j] + M[junc_rows, _col_left(j+1, N)] .= uShootL[j+1] else # Edge junction M[junc_rows, _col_right(msing, N)] .= uShootR[msing] if wv !== nothing - M[junc_rows[1:N], col_edge] .= -I(N) - M[junc_rows[N+1:end], col_edge] .= wv .* psio^2 + M[junc_rows[1:N], col_edge] .= -I(N) + M[junc_rows[(N+1):end], col_edge] .= wv .* psio^2 else - M[junc_rows[N+1:end], col_edge] .= -I(N) + M[junc_rows[(N+1):end], col_edge] .= -I(N) end end row_offset = last(junc_rows) @@ -635,7 +643,7 @@ function _assemble_bvp_S_axis(uShootR::Vector{Matrix{ComplexF64}}, for j in 1:msing ipert_j = ipert_all[j] row_offset += 1 - M[row_offset, _col_left(j, N)[ipert_j]] = 1 + M[row_offset, _col_left(j, N)[ipert_j]] = 1 row_offset += 1 M[row_offset, _col_right(j, N)[ipert_j]] = 1 end @@ -670,18 +678,18 @@ end # Fallback BVP assembly with FM-based axis BC (used when no Riccati S matrices are available). # Uses the conditioned axis propagator Phi_R[1][:,N+1:2N] in place of S-axis matching. function _assemble_bvp_FM_axis(Phi_L_mats::Vector{Matrix{ComplexF64}}, - Phi_R_mats::Vector{Matrix{ComplexF64}}, ipert_all::Vector{Int}, - msing::Int, N::Int, - T_left_inv::Vector{Matrix{ComplexF64}}, - T_right_inv::Vector{Matrix{ComplexF64}}, has_ua::Bool, - wv::Union{Nothing,Matrix{ComplexF64}}, psio::Float64) + Phi_R_mats::Vector{Matrix{ComplexF64}}, ipert_all::Vector{Int}, + msing::Int, N::Int, + T_left_inv::Vector{Matrix{ComplexF64}}, + T_right_inv::Vector{Matrix{ComplexF64}}, has_ua::Bool, + wv::Union{Nothing,Matrix{ComplexF64}}, psio::Float64) nMat = (2 + 4 * msing) * N col_axis = 1:N - col_edge = (N + 4N*msing + 1):nMat + col_edge = (N+4N*msing+1):nMat M = zeros(ComplexF64, nMat, nMat) M[1:2N, (N+1):(N+2N)] .= Phi_L_mats[1] - M[1:2N, col_axis] .= -view(Phi_R_mats[1], :, N+1:2N) + M[1:2N, col_axis] .= -view(Phi_R_mats[1], :, (N+1):2N) row_drive_base = 2N + (4N-2)*msing for j in 1:msing @@ -692,29 +700,29 @@ function _assemble_bvp_FM_axis(Phi_L_mats::Vector{Matrix{ComplexF64}}, for i in 1:2N if i != ipert_j && i != ipert_j + N row_cont += 1 - M[row_cont, cl[i]] = 1 + M[row_cont, cl[i]] = 1 M[row_cont, cr[i]] = -1 end end - junc_rows = (row_cont + 1):(2N + (4N-2)*j) + junc_rows = (row_cont+1):(2N+(4N-2)*j) if j < msing - M[junc_rows, cr] .= Phi_R_mats[j+1] + M[junc_rows, cr] .= Phi_R_mats[j+1] M[junc_rows, _col_left(j+1, N)] .= -Phi_L_mats[j+1] else M[junc_rows, cr] .= Phi_R_mats[msing+1] if wv !== nothing - M[junc_rows[1:N], col_edge] .= -I(N) - M[junc_rows[N+1:end], col_edge] .= wv .* psio^2 + M[junc_rows[1:N], col_edge] .= -I(N) + M[junc_rows[(N+1):end], col_edge] .= wv .* psio^2 else - M[junc_rows[N+1:end], col_edge] .= -I(N) + M[junc_rows[(N+1):end], col_edge] .= -I(N) end end if has_ua - M[row_drive_base + 2j-1, cl] .= T_left_inv[j][ipert_j, :] - M[row_drive_base + 2j, cr] .= T_right_inv[j][ipert_j, :] + M[row_drive_base+2j-1, cl] .= T_left_inv[j][ipert_j, :] + M[row_drive_base+2j, cr] .= T_right_inv[j][ipert_j, :] else - M[row_drive_base + 2j-1, cl[ipert_j]] = 1 - M[row_drive_base + 2j, cr[ipert_j]] = 1 + M[row_drive_base+2j-1, cl[ipert_j]] = 1 + M[row_drive_base+2j, cr[ipert_j]] = 1 end end return M, nMat, col_edge @@ -725,8 +733,8 @@ end # combination subtracts dp_raw entries up to ~3×10⁴ larger than the result, and Float64 # precision lets the imaginary part drift 2–5× on DIIID-class equilibria. function _solve_bvp_and_combine_pest3(M::Matrix{ComplexF64}, msing::Int, N::Int, nMat::Int, - use_S_axis::Bool, ipert_all::Vector{Int}, col_edge, - ctrl, debug::Bool) + use_S_axis::Bool, ipert_all::Vector{Int}, col_edge, + ctrl, debug::Bool) s2 = 2 * msing Tc = (ctrl === nothing || ctrl.extended_precision_bvp) ? Complex{Double64} : ComplexF64 M_solve = Tc.(M) @@ -748,12 +756,12 @@ function _solve_bvp_and_combine_pest3(M::Matrix{ComplexF64}, msing::Int, N::Int, x = use_lu ? (M_lu \ b) : (M_pinv * b) debug && _log_bvp_solve(x, b, M_solve, jsing, side, dRow, msing, N, - ipert_all, col_edge, use_S_axis) + ipert_all, col_edge, use_S_axis) for ksing in 1:msing ipert_k = ipert_all[ksing] dp_raw[dRow, 2ksing-1] = x[_col_left(ksing, N)[ipert_k+N]] - dp_raw[dRow, 2ksing] = x[_col_right(ksing, N)[ipert_k+N]] + dp_raw[dRow, 2ksing] = x[_col_right(ksing, N)[ipert_k+N]] end end @@ -773,7 +781,7 @@ end # Logging helpers for `compute_delta_prime_matrix!`. Called only when debug=true. function _log_bvp_setup(chunks, sing, S_at_surface_left, use_S_axis, has_ua, - Phi_L_mats, Phi_R_mats, Phi_R_halves, ipert_all, wv, psio, N, msing) + Phi_L_mats, Phi_R_mats, Phi_R_halves, ipert_all, wv, psio, N, msing) @info "Δ' BVP: $(length(chunks)) chunks, $msing surfaces, N=$N" @info "Δ' BVP: Axis BC: $(use_S_axis ? "S-based (Riccati)" : "FM-based (conditioned)")" @info "Δ' BVP: Asymptotic basis: $(has_ua ? "available" : "NOT available (raw basis driving)")" @@ -785,8 +793,8 @@ function _log_bvp_setup(chunks, sing, S_at_surface_left, use_S_axis, has_ua, if has_ua for j in 1:msing sp = sing[j] - T_l = [sp.ua_left[:,:,1]; sp.ua_left[:,:,2]] - T_r = [sp.ua_right[:,:,1]; sp.ua_right[:,:,2]] + T_l = [sp.ua_left[:, :, 1]; sp.ua_left[:, :, 2]] + T_r = [sp.ua_right[:, :, 1]; sp.ua_right[:, :, 2]] @info " Surface $j: cond(T_left)=$(@sprintf("%.2e", cond(T_l))), cond(T_right)=$(@sprintf("%.2e", cond(T_r)))" ipert_j = ipert_all[j] @info " Surface $j ua_left (ipert=$ipert_j, psi_ua_left=$(@sprintf("%.8f", sp.psi_ua_left))):" @@ -796,7 +804,7 @@ function _log_bvp_setup(chunks, sing, S_at_surface_left, use_S_axis, has_ua, @info " small: ua(1,$(ipert_j+N),1)=$(@sprintf("%16.8e %16.8e", real(sp.ua_left[1,ipert_j+N,1]), imag(sp.ua_left[1,ipert_j+N,1])))" end end - for j in 1:msing-1 + for j in 1:(msing-1) Phi_L_h, Phi_R_h = Phi_R_halves[j] @info " Inter-surface $j→$(j+1): half_L cond=$(@sprintf("%.2e",cond(Phi_L_h))), half_R cond=$(@sprintf("%.2e",cond(Phi_R_h))), full cond=$(@sprintf("%.2e",cond(Phi_R_mats[j+1])))" end @@ -813,7 +821,7 @@ function _log_bvp_setup(chunks, sing, S_at_surface_left, use_S_axis, has_ua, end function _log_S_axis_shooting_propagators(uShootR, uShootL, uAxis, S_at_surface_left, - T_left_mats, ipert_all, has_ua, msing, N) + T_left_mats, ipert_all, has_ua, msing, N) @info " Shooting propagators (S-based axis BC, no axis unknowns):" for j in 1:msing shoot_R_str = @sprintf("%.2e", cond(uShootR[j])) @@ -823,7 +831,7 @@ function _log_S_axis_shooting_propagators(uShootR, uShootL, uAxis, S_at_surface_ S1 = S_at_surface_left[1] if has_ua T1 = T_left_mats[1] - axis_BC = T1[1:N, :] - S1 * T1[N+1:2N, :] + axis_BC = T1[1:N, :] - S1 * T1[(N+1):2N, :] @info " S-axis BC matrix: cond=$(@sprintf("%.2e", cond(axis_BC)))" end for j in 1:msing @@ -837,7 +845,7 @@ function _log_S_axis_shooting_propagators(uShootR, uShootL, uAxis, S_at_surface_ @info " uShootL[$j] col ipert=$ipert_j norm=$(@sprintf("%.2e", col_norms_L[ipert_j])), col ipert+N=$(ipert_j+N) norm=$(@sprintf("%.2e", col_norms_L[ipert_j+N]))" end end - for j in 1:msing-1 + for j in 1:(msing-1) mid_block = hcat(uShootR[j], -uShootL[j+1]) @info " Midpoint $j→$(j+1): cond([uShootR[$j] | -uShootL[$(j+1)]]) = $(@sprintf("%.2e", cond(mid_block)))" col_norms_Ljp1 = [norm(view(uShootL[j+1], :, k)) for k in 1:2N] @@ -846,7 +854,7 @@ function _log_S_axis_shooting_propagators(uShootR, uShootL, uAxis, S_at_surface_ end function _log_bvp_solve(x, b, M_solve, jsing, side, dRow, msing, N, - ipert_all, col_edge, use_S_axis) + ipert_all, col_edge, use_S_axis) residual = norm(ComplexF64.(M_solve * x - b)) side_str = side == 1 ? "left" : "right" @info " BVP solve: jsing=$jsing side=$side_str (dRow=$dRow): ||Mx-b||=$(@sprintf("%.2e", residual)), ||x||=$(@sprintf("%.2e", Float64(norm(x))))" @@ -854,9 +862,9 @@ function _log_bvp_solve(x, b, M_solve, jsing, side, dRow, msing, N, ipert_ks = ipert_all[ks] cl = _col_left(ks, N) cr = _col_right(ks, N) - xl_big = ComplexF64(x[cl[ipert_ks]]) + xl_big = ComplexF64(x[cl[ipert_ks]]) xl_small = ComplexF64(x[cl[ipert_ks+N]]) - xr_big = ComplexF64(x[cr[ipert_ks]]) + xr_big = ComplexF64(x[cr[ipert_ks]]) xr_small = ComplexF64(x[cr[ipert_ks+N]]) @info " surf $ks: x_left[big]=$(@sprintf("%+.4e%+.4ei", real(xl_big), imag(xl_big))), x_left[small]=$(@sprintf("%+.4e%+.4ei", real(xl_small), imag(xl_small)))" @info " surf $ks: x_right[big]=$(@sprintf("%+.4e%+.4ei", real(xr_big), imag(xr_big))), x_right[small]=$(@sprintf("%+.4e%+.4ei", real(xr_small), imag(xr_small)))" @@ -870,7 +878,7 @@ end function _log_bvp_pest3(dp_raw, deltap, s2, msing, Tc) @info "Δ' BVP: Full dp_raw matrix ($(s2)×$(s2)) [$(Tc)]:" for i in 1:s2 - row_str = join([@sprintf("%+.6e", Float64(real(dp_raw[i,j]))) for j in 1:s2], " ") + row_str = join([@sprintf("%+.6e", Float64(real(dp_raw[i, j]))) for j in 1:s2], " ") @info " dp_raw[$i,:] = $row_str" end @info "Δ' BVP: Raw dp diagonal = $([@sprintf("%.4f%+.4fi", Float64(real(dp_raw[i,i])), Float64(imag(dp_raw[i,i]))) for i in 1:s2])" @@ -930,8 +938,8 @@ function pest3_decompose(dp_raw::AbstractMatrix) for i in 1:m, j in 1:m LL = dp_raw[2i-1, 2j-1] LR = dp_raw[2i-1, 2j] - RL = dp_raw[2i, 2j-1] - RR = dp_raw[2i, 2j] + RL = dp_raw[2i, 2j-1] + RR = dp_raw[2i, 2j] Ap[i, j] = RR + RL + LR + LL Bp[i, j] = RR - RL + LR - LL Gp[i, j] = RR + RL - LR - LL @@ -944,7 +952,7 @@ end riccati_der!(du, u, params, psieval) Evaluate the explicit dual Riccati ODE right-hand side: - dS/dψ = w†·F̄⁻¹·w - S·Ḡ·S, w = Q - K̄·S +dS/dψ = w†·F̄⁻¹·w - S·Ḡ·S, w = Q - K̄·S where Q = diag(1/(m - n·q)) is the diagonal singular factor matrix. The identity slice u[:,:,2] = I does not evolve (du[:,:,2] = 0). @@ -968,7 +976,7 @@ See: Glasser (2018) Phys. Plasmas 25, 032507 — Eq. 19 (dual Riccati form) _, equil, ffit, intr, odet, _ = params Npert = intr.numpert_total - S = @view u[:, :, 1] + S = @view u[:, :, 1] dS = @view du[:, :, 1] @view(du[:, :, 2]) .= 0 # identity does not evolve @@ -983,9 +991,9 @@ See: Glasser (2018) Phys. Plasmas 25, 032507 — Eq. 19 (dual Riccati form) fmat_lower = acquire!(pool, ComplexF64, Npert, Npert) kmat = similar!(pool, fmat_lower) gmat = similar!(pool, fmat_lower) - w = similar!(pool, fmat_lower) # w = Q - K̄·S - v = similar!(pool, fmat_lower) # v = F̄⁻¹·w (then reused for S·Ḡ·S) - tmp = similar!(pool, fmat_lower) # scratch + w = similar!(pool, fmat_lower) # w = Q - K̄·S + v = similar!(pool, fmat_lower) # v = F̄⁻¹·w (then reused for S·Ḡ·S) + tmp = similar!(pool, fmat_lower) # scratch # Evaluate F̄ (Cholesky factor), K̄, Ḡ splines at current ψ ffit.fmats_lower(vec(fmat_lower), psieval; hint=ffit._hint) @@ -1076,7 +1084,7 @@ function riccati_integrate_chunk!( cb = DiscreteCallback((u, t, integrator) -> true, riccati_integrator_callback!) rtol = ctrl.eulerlagrange_tolerance prob = ODEProblem(sing_der!, odet.u, (chunk.psi_start, chunk.psi_end), - (ctrl, equil, ffit, intr, odet, chunk)) + (ctrl, equil, ffit, intr, odet, chunk)) sol = solve(prob, Vern9(); reltol=rtol, callback=cb, save_everystep=false, save_end=true) odet.u .= sol.u[end] odet.psifac = sol.t[end] @@ -1094,8 +1102,8 @@ end renormalize_riccati!(odet, intr) After a singular surface crossing, restore the canonical Riccati storage convention: - u[:,:,1] = S_new = U₁_new · U₂_new⁻¹ - u[:,:,2] = I +u[:,:,1] = S_new = U₁_new · U₂_new⁻¹ +u[:,:,2] = I `riccati_cross_ideal_singular_surf!` leaves u[:,:,1] = U₁_new and u[:,:,2] = U₂_new (not I), so this step is required before continuing the Riccati integration. @@ -1119,8 +1127,8 @@ end renormalize_riccati_inplace!(u, N) In-place Riccati renormalization on an arbitrary N×N×2 array: - u[:,:,1] = U₁ · U₂⁻¹ (new S) - u[:,:,2] = I +u[:,:,1] = U₁ · U₂⁻¹ (new S) +u[:,:,2] = I Used in `riccati_integrator_callback!` to renormalize the integrator's live state when column norms grow beyond `ctrl.ucrit`, analogous to Gaussian reduction in the @@ -1142,14 +1150,14 @@ end Cross a singular surface for the Riccati formulation. Replaces `cross_ideal_singular_surf!` for the Riccati integration path with two key differences: -1. **No Gaussian reduction**: `cross_ideal_singular_surf!` calls `compute_solution_norms!` - which applies Gaussian reduction to (S, I). This divides by pivot elements of S, which - can be near-zero (S = 0 at axis and grows slowly), producing NaN/Inf in U₂. For Riccati, - S is bounded so Gaussian reduction is unnecessary. + 1. **No Gaussian reduction**: `cross_ideal_singular_surf!` calls `compute_solution_norms!` + which applies Gaussian reduction to (S, I). This divides by pivot elements of S, which + can be near-zero (S = 0 at axis and grows slowly), producing NaN/Inf in U₂. For Riccati, + S is bounded so Gaussian reduction is unnecessary. -2. **Direct column zeroing**: Instead of using the GR-sorted `odet.index` to identify the - column to zero, we use `ipert_res` directly (the resonant mode index). This is valid since - without GR there is no permutation applied to the columns of S. + 2. **Direct column zeroing**: Instead of using the GR-sorted `odet.index` to identify the + column to zero, we use `ipert_res` directly (the resonant mode index). This is valid since + without GR there is no permutation applied to the columns of S. **Δ' normalization**: This function expects `odet.u` in the bounded (U₁, U₂) form produced by `riccati_integrate_chunk!` with `needs_crossing=true` (final renorm skipped). ca_l is computed @@ -1195,11 +1203,11 @@ Fortran STRIDE's separate vmatl/vmatr (sing_vmat). Alpha is taken from the right side and shared with the left. """ function _two_sided_singular_asymptotics(singp::SingType, ctrl::ForceFreeStatesControl, - equil::Equilibrium.PlasmaEquilibrium, ffit::FourFitVars, - intr::ForceFreeStatesInternal) + equil::Equilibrium.PlasmaEquilibrium, ffit::FourFitVars, + intr::ForceFreeStatesInternal) sing_asymp_right = compute_sing_asymptotics(singp, ctrl, equil, ffit, intr; sig=1.0) - sing_asymp_left = compute_sing_asymptotics(singp, ctrl, equil, ffit, intr; sig=-1.0, - alpha_override=sing_asymp_right.alpha) + sing_asymp_left = compute_sing_asymptotics(singp, ctrl, equil, ffit, intr; sig=-1.0, + alpha_override=sing_asymp_right.alpha) return sing_asymp_left, sing_asymp_right end @@ -1219,7 +1227,7 @@ end # Capture left-side asymptotic data into odet.ca_l and singp.ua_left/psi_ua_left. function _capture_left_crossing_data!(odet::OdeState, singp::SingType, sing_asymp_left, - dpsi::Float64, intr::ForceFreeStatesInternal, ising::Int) + dpsi::Float64, intr::ForceFreeStatesInternal, ising::Int) ua = sing_get_ua(sing_asymp_left, dpsi) singp.ua_left = copy(ua) singp.psi_ua_left = odet.psifac @@ -1231,9 +1239,9 @@ end # odet.psifac to the right side. The zeroed columns stay zero through the predictor # since du[:, ipert_res, :] = 0 when u[:, ipert_res, :] = 0. function _predict_across_singular_surface!(odet::OdeState, ctrl::ForceFreeStatesControl, - equil::Equilibrium.PlasmaEquilibrium, ffit::FourFitVars, - intr::ForceFreeStatesInternal, ising::Int, - ipert_res, dpsi::Float64, sing_asymp_right) + equil::Equilibrium.PlasmaEquilibrium, ffit::FourFitVars, + intr::ForceFreeStatesInternal, ising::Int, + ipert_res, dpsi::Float64, sing_asymp_right) if ctrl.kinetic_factor == 0 for i in eachindex(sing_asymp_right.r1) odet.u[:, ipert_res[i], :] .= 0 @@ -1253,8 +1261,8 @@ end # Column ipert_res of [U₁_new; U₂_new] = ua[:, ipert_res+N, :] (the introduced small asymptotic), # so ca_r[ipert_res, ipert_res, 2] = 1 regardless of other columns' normalization. function _capture_right_crossing_data!(odet::OdeState, singp::SingType, sing_asymp_right, - dpsi::Float64, intr::ForceFreeStatesInternal, ising::Int, - ipert_res, ctrl::ForceFreeStatesControl) + dpsi::Float64, intr::ForceFreeStatesInternal, ising::Int, + ipert_res, ctrl::ForceFreeStatesControl) ua = sing_get_ua(sing_asymp_right, dpsi) singp.ua_right = copy(ua) singp.psi_ua_right = odet.psifac @@ -1270,9 +1278,9 @@ end # STUB: per-surface ca-based Δ' (not physically valid; see SingType.delta_prime docstring). # The canonical Δ' is intr.delta_prime_matrix from compute_delta_prime_matrix!. function _stash_per_surface_delta_prime_stub!(odet::OdeState, intr::ForceFreeStatesInternal, - ising::Int, ipert_res, sing_asymp_right, - equil::Equilibrium.PlasmaEquilibrium, - ctrl::ForceFreeStatesControl) + ising::Int, ipert_res, sing_asymp_right, + equil::Equilibrium.PlasmaEquilibrium, + ctrl::ForceFreeStatesControl) ctrl.kinetic_factor == 0 || return denom = (2π)^2 * equil.psio n_res = length(sing_asymp_right.r1) @@ -1323,8 +1331,8 @@ function integrate_propagator_chunk!( # naturally. The resulting propagator maps state at psi_end → psi_start, which is # well-conditioned because exponentially growing solutions (forward) decay backward. tspan = chunk.direction == 1 ? - (chunk.psi_start, chunk.psi_end) : - (chunk.psi_end, chunk.psi_start) + (chunk.psi_start, chunk.psi_end) : + (chunk.psi_end, chunk.psi_start) rtol = ctrl.eulerlagrange_tolerance params = (ctrl, equil, ffit, intr, odet_proxy, chunk) @@ -1378,12 +1386,12 @@ function integrate_fm_with_ua_ic( equil::Equilibrium.PlasmaEquilibrium, ffit::FourFitVars, intr::ForceFreeStatesInternal; - backward::Bool = false, - psi_ua::Float64 = NaN + backward::Bool=false, + psi_ua::Float64=NaN ) N = intr.numpert_total psi_start = chunks[first(chunk_range)].psi_start - psi_end = chunks[last(chunk_range)].psi_end + psi_end = chunks[last(chunk_range)].psi_end # Use stored ua ψ location if provided; otherwise fall back to chunk boundary. # The ua is evaluated at the inner-layer boundary (exact ψ from singular crossing), # which may differ slightly from the nearest chunk boundary. @@ -1409,18 +1417,18 @@ function integrate_fm_with_ua_ic( odet_proxy.ffit_hint[] = 1 prob = ODEProblem(sing_der!, u0, tspan, params) sol = solve(prob, Vern9(); reltol=rtol, save_everystep=false, save_end=true) - result[1:N, 1:N] .= sol.u[end][:, :, 1] - result[N+1:2N, 1:N] .= sol.u[end][:, :, 2] + result[1:N, 1:N] .= sol.u[end][:, :, 1] + result[(N+1):2N, 1:N] .= sol.u[end][:, :, 2] # Batch 2: columns N+1:2N of T (small solutions) - u0[:, :, 1] .= ua[:, N+1:2N, 1] - u0[:, :, 2] .= ua[:, N+1:2N, 2] + u0[:, :, 1] .= ua[:, (N+1):2N, 1] + u0[:, :, 2] .= ua[:, (N+1):2N, 2] odet_proxy.spline_hint[] = 1 odet_proxy.ffit_hint[] = 1 prob = ODEProblem(sing_der!, u0, tspan, params) sol = solve(prob, Vern9(); reltol=rtol, save_everystep=false, save_end=true) - result[1:N, N+1:2N] .= sol.u[end][:, :, 1] - result[N+1:2N, N+1:2N] .= sol.u[end][:, :, 2] + result[1:N, (N+1):2N] .= sol.u[end][:, :, 1] + result[(N+1):2N, (N+1):2N] .= sol.u[end][:, :, 2] return result end @@ -1432,8 +1440,8 @@ Apply the chunk propagator `prop` to the current state `odet.u` in-place. The propagator acts as a linear map on the (U₁, U₂) pair: - U₁_new = block_upper_ic[:,:,1] · U₁_prev + block_lower_ic[:,:,1] · U₂_prev - U₂_new = block_upper_ic[:,:,2] · U₁_prev + block_lower_ic[:,:,2] · U₂_prev +U₁_new = block_upper_ic[:,:,1] · U₁_prev + block_lower_ic[:,:,1] · U₂_prev +U₂_new = block_upper_ic[:,:,2] · U₁_prev + block_lower_ic[:,:,2] · U₂_prev This correctly propagates any state (not just the identity), including the (S, I) form produced by Riccati-style crossings. @@ -1488,10 +1496,10 @@ function apply_propagator_inverse!(odet::OdeState, prop::ChunkPropagator) # Φ_bwd maps state at psi_end → psi_start (well-conditioned). # We want Φ_fwd = Φ_bwd⁻¹ to advance state from psi_start → psi_end. # Solving Φ_bwd · x = [U₁_old; U₂_old] gives x = Φ_bwd⁻¹ · [U₁_old; U₂_old]. - u_old = [odet.u[:,:,1]; odet.u[:,:,2]] # 2N × N + u_old = [odet.u[:, :, 1]; odet.u[:, :, 2]] # 2N × N u_new = Φ \ u_old # LU solve, 2N × N - odet.u[:,:,1] .= u_new[1:N, :] - odet.u[:,:,2] .= u_new[N+1:2N, :] + odet.u[:, :, 1] .= u_new[1:N, :] + odet.u[:, :, 2] .= u_new[(N+1):2N, :] end """ @@ -1504,33 +1512,34 @@ this is the only branch that produces them. Solves the same system as [`forward_eulerlagrange_integration`](@ref), but integrates all bulk chunks concurrently using `Threads.@threads`, then re-integrates the outer plasma serially: -1. **Chunk generation**: calls `chunk_el_integration_bounds`, then `balance_integration_chunks` - to sub-divide chunks for load balancing. The chunk count depends only on `intr.msing` and - `ctrl.nchunks`, never on the thread count, so results are thread-independent. -2. **Propagator phase**: `integrate_propagator_chunk!` integrates each chunk independently - from identity initial conditions (no accumulated state, no normalization/callback). - Each thread uses a private `OdeState` proxy for `sing_der!` side effects. -3. **Serial assembly**: propagators are applied sequentially with `apply_propagator!`. - Rational surface crossings use `riccati_cross_ideal_singular_surf!` (no Gaussian - reduction). -4. **Outer plasma re-integration**: after the last rational surface crossing, the outer - plasma (from last ψ_s to psilim) is re-integrated using `riccati_integrate_chunk!`. - FM propagation in this region is prone to precision loss for high N (exponential growth - without renormalization); Riccati integration keeps matrices bounded and provides dense - checkpoints for `findmax_dW_edge!`. + 1. **Chunk generation**: calls `chunk_el_integration_bounds`, then `balance_integration_chunks` + to sub-divide chunks for load balancing. The chunk count depends only on `intr.msing` and + `ctrl.nchunks`, never on the thread count, so results are thread-independent. + 2. **Propagator phase**: `integrate_propagator_chunk!` integrates each chunk independently + from identity initial conditions (no accumulated state, no normalization/callback). + Each thread uses a private `OdeState` proxy for `sing_der!` side effects. + 3. **Serial assembly**: propagators are applied sequentially with `apply_propagator!`. + Rational surface crossings use `riccati_cross_ideal_singular_surf!` (no Gaussian + reduction). + 4. **Outer plasma re-integration**: after the last rational surface crossing, the outer + plasma (from last ψ_s to psilim) is re-integrated using `riccati_integrate_chunk!`. + FM propagation in this region is prone to precision loss for high N (exponential growth + without renormalization); Riccati integration keeps matrices bounded and provides dense + checkpoints for `findmax_dW_edge!`. Select via `integrator = "riccati"` in `[ForceFreeStates]` of gpec.toml. Requires `singfac_min != 0`. Uses whatever threads `julia -t` provides; `ctrl.nchunks` is the only tunable. **Key differences from the forward integrator:** -- No Gaussian reduction in the propagator BVP phase (crossings use the - Riccati-style algorithm, `odet.ifix` stays 0) -- `transform_u!` is called on the odet but is a no-op (ifix=0) -- Outer plasma uses serial Riccati integration for numerical stability -- `odet.u_store` holds chunk-endpoint Riccati states, not dense Euler-Lagrange ξ, and - `odet.u_store_el_basis` stays `false`: this integrator never claims the EL basis, so - PerturbedEquilibrium and the HDF5 forward-integration ξ datasets require the forward path. + + - No Gaussian reduction in the propagator BVP phase (crossings use the + Riccati-style algorithm, `odet.ifix` stays 0) + - `transform_u!` is called on the odet but is a no-op (ifix=0) + - Outer plasma uses serial Riccati integration for numerical stability + - `odet.u_store` holds chunk-endpoint Riccati states, not dense Euler-Lagrange ξ, and + `odet.u_store_el_basis` stays `false`: this integrator never claims the EL basis, so + PerturbedEquilibrium and the HDF5 forward-integration ξ datasets require the forward path. **Bidirectional integration for large-N accuracy:** The crossing chunk (nearest to each rational surface singL[j]) is integrated *backward* @@ -1577,9 +1586,9 @@ end # Build odet and initialize at the magnetic axis. Same path as serial eulerlagrange_integration. function _initialize_parallel_odet(ctrl::ForceFreeStatesControl, - equil::Equilibrium.PlasmaEquilibrium, - ffit::FourFitVars, - intr::ForceFreeStatesInternal) + equil::Equilibrium.PlasmaEquilibrium, + ffit::FourFitVars, + intr::ForceFreeStatesInternal) odet = OdeState(intr.numpert_total, ctrl.numsteps_init, ctrl.numunorms_init, intr.msing) if ctrl.sing_start <= 0 initialize_el_at_axis!(odet, ctrl, ffit, equil.profiles, intr) @@ -1598,7 +1607,7 @@ end # per-thread proxy OdeStates sized by maxthreadid() (Julia 1.9+ may report threadid # values above nthreads() due to the interactive thread pool). function _setup_parallel_chunks_and_proxies(odet::OdeState, ctrl::ForceFreeStatesControl, - intr::ForceFreeStatesInternal) + intr::ForceFreeStatesInternal) # Bidirectional chunks: crossing chunks are assigned direction=-1 so they are # integrated backward. The resulting Φ_bwd is well-conditioned because growing EL # solutions decay backward; forward propagation is recovered via LU solve in @@ -1612,8 +1621,8 @@ function _setup_parallel_chunks_and_proxies(odet::OdeState, ctrl::ForceFreeState end function _log_parallel_start(ctrl::ForceFreeStatesControl, odet::OdeState, - equil::Equilibrium.PlasmaEquilibrium, - chunks::Vector{IntegrationChunk}) + equil::Equilibrium.PlasmaEquilibrium, + chunks::Vector{IntegrationChunk}) ctrl.verbose || return @info " ψ = $((@sprintf "%.3f" odet.psifac)), q = $((@sprintf "%.3f" equil.profiles.q_spline(odet.psifac)))" @info " Riccati FM: $(length(chunks)) chunks over $(Threads.nthreads()) thread$(Threads.nthreads() == 1 ? "" : "s")" @@ -1624,14 +1633,14 @@ end # Each chunk is independent (identity IC, no accumulated state), so the result does not # depend on how chunks are distributed across threads. function _run_parallel_bvp_phase!(propagators::Vector{ChunkPropagator}, - chunks::Vector{IntegrationChunk}, - ctrl::ForceFreeStatesControl, - equil::Equilibrium.PlasmaEquilibrium, ffit::FourFitVars, - intr::ForceFreeStatesInternal, - odet_proxies::Vector{OdeState}) + chunks::Vector{IntegrationChunk}, + ctrl::ForceFreeStatesControl, + equil::Equilibrium.PlasmaEquilibrium, ffit::FourFitVars, + intr::ForceFreeStatesInternal, + odet_proxies::Vector{OdeState}) Threads.@threads :static for i in eachindex(chunks) integrate_propagator_chunk!(propagators[i], chunks[i], ctrl, equil, ffit, intr, - odet_proxies[Threads.threadid()]) + odet_proxies[Threads.threadid()]) end end @@ -1643,10 +1652,10 @@ end # the well-conditioned Riccati S at each surface's left boundary for use as the Δ' BVP # axis BC. Returns (S_at_surface_left, last_crossing_step). function _assemble_propagators_serially!(odet::OdeState, propagators::Vector{ChunkPropagator}, - chunks::Vector{IntegrationChunk}, - ctrl::ForceFreeStatesControl, - equil::Equilibrium.PlasmaEquilibrium, - ffit::FourFitVars, intr::ForceFreeStatesInternal) + chunks::Vector{IntegrationChunk}, + ctrl::ForceFreeStatesControl, + equil::Equilibrium.PlasmaEquilibrium, + ffit::FourFitVars, intr::ForceFreeStatesInternal) N = intr.numpert_total S_at_surface_left = Matrix{ComplexF64}[] last_crossing_step = 1 @@ -1693,9 +1702,9 @@ end # entry at last_crossing_step holds (U₁_new, U₂_new) from riccati_cross_ideal_singular_surf! # before renormalization; we renorm here to (S_new, I) as the Riccati starting state. function _reintegrate_outer_plasma!(odet::OdeState, last_crossing_step::Int, - ctrl::ForceFreeStatesControl, - equil::Equilibrium.PlasmaEquilibrium, ffit::FourFitVars, - intr::ForceFreeStatesInternal) + ctrl::ForceFreeStatesControl, + equil::Equilibrium.PlasmaEquilibrium, ffit::FourFitVars, + intr::ForceFreeStatesInternal) N = intr.numpert_total odet.u .= odet.u_store[:, :, :, last_crossing_step] odet.psifac = odet.psi_store[last_crossing_step] @@ -1703,7 +1712,7 @@ function _reintegrate_outer_plasma!(odet::OdeState, last_crossing_step::Int, odet.step = last_crossing_step + 1 renormalize_riccati_inplace!(odet.u, N) outer_chunk = IntegrationChunk(; psi_start=odet.psifac, psi_end=intr.psilim * (1 - eps), - needs_crossing=false, ising=0) + needs_crossing=false, ising=0) riccati_integrate_chunk!(odet, ctrl, equil, ffit, intr, outer_chunk) # Post: odet.u is in (S, I) form; odet.step points to next empty slot. end @@ -1717,10 +1726,10 @@ end # original psilim — silently shifting the outermost rational's Δ' by tens of percent. # Returns the (possibly truncated) chunks and propagators arrays. function _handle_edge_dW_scan!(odet::OdeState, chunks::Vector{IntegrationChunk}, - propagators::Vector{ChunkPropagator}, - ctrl::ForceFreeStatesControl, - equil::Equilibrium.PlasmaEquilibrium, ffit::FourFitVars, - intr::ForceFreeStatesInternal) + propagators::Vector{ChunkPropagator}, + ctrl::ForceFreeStatesControl, + equil::Equilibrium.PlasmaEquilibrium, ffit::FourFitVars, + intr::ForceFreeStatesInternal) N = intr.numpert_total odet.step -= 1 trim_storage!(odet) @@ -1754,22 +1763,22 @@ function _handle_edge_dW_scan!(odet::OdeState, chunks::Vector{IntegrationChunk}, end straddling = chunks[last_chunk_idx] if straddling.psi_end > peak_psi - new_chunk = IntegrationChunk( - psi_start = straddling.psi_start, - psi_end = peak_psi, - needs_crossing = straddling.needs_crossing, - ising = straddling.ising, - direction = straddling.direction, + new_chunk = IntegrationChunk(; + psi_start=straddling.psi_start, + psi_end=peak_psi, + needs_crossing=straddling.needs_crossing, + ising=straddling.ising, + direction=straddling.direction ) chunks[last_chunk_idx] = new_chunk odet_proxy = OdeState(N, 1, 1, 0) integrate_propagator_chunk!(propagators[last_chunk_idx], new_chunk, - ctrl, equil, ffit, intr, odet_proxy) + ctrl, equil, ffit, intr, odet_proxy) end n_dropped = 0 if last_chunk_idx < length(chunks) n_dropped = length(chunks) - last_chunk_idx - chunks = chunks[1:last_chunk_idx] + chunks = chunks[1:last_chunk_idx] propagators = propagators[1:last_chunk_idx] end if ctrl.verbose diff --git a/src/ForceFreeStates/Sing.jl b/src/ForceFreeStates/Sing.jl index 960530f6a..33694477a 100644 --- a/src/ForceFreeStates/Sing.jl +++ b/src/ForceFreeStates/Sing.jl @@ -123,9 +123,11 @@ function sing_lim!(intr::ForceFreeStatesInternal, ctrl::ForceFreeStatesControl, # strategy. Multi-n runs are not supported — the "outermost rational + dmlim/n" cutoff depends # on which n is used — and fall back to qhigh / psihigh truncation with a warning. if ctrl.set_psilim_via_dmlim && intr.nlow <= 0 - error("sing_lim!: set_psilim_via_dmlim = true requires a resolved toroidal range, but got intr.nlow=$(intr.nlow). " * - "Assign intr.nlow / intr.nhigh (from ctrl.nn_low / ctrl.nn_high) before calling sing_lim!, " * - "or set set_psilim_via_dmlim = false to truncate via qhigh / psihigh instead.") + error( + "sing_lim!: set_psilim_via_dmlim = true requires a resolved toroidal range, but got intr.nlow=$(intr.nlow). " * + "Assign intr.nlow / intr.nhigh (from ctrl.nn_low / ctrl.nn_high) before calling sing_lim!, " * + "or set set_psilim_via_dmlim = false to truncate via qhigh / psihigh instead." + ) elseif ctrl.set_psilim_via_dmlim && intr.nlow != intr.nhigh @warn "set_psilim_via_dmlim = true is ignored for multi-n runs (nn_low=$(intr.nlow), nn_high=$(intr.nhigh)); falling back to qhigh / psihigh truncation." elseif ctrl.set_psilim_via_dmlim diff --git a/src/ForcingTerms/BiotSavart.jl b/src/ForcingTerms/BiotSavart.jl index c03ab07c6..cd0bbb79e 100644 --- a/src/ForcingTerms/BiotSavart.jl +++ b/src/ForcingTerms/BiotSavart.jl @@ -45,27 +45,30 @@ Build contiguous segment-vector and midpoint arrays for strand `(j,k)` of coil s function precompute_segments(cs::CoilSet, j::Int, k::Int, current_nw::Float64) nsec = cs.nsec nseg = nsec - 1 - dlx = Vector{Float64}(undef, nseg) - dly = Vector{Float64}(undef, nseg) - dlz = Vector{Float64}(undef, nseg) + dlx = Vector{Float64}(undef, nseg) + dly = Vector{Float64}(undef, nseg) + dlz = Vector{Float64}(undef, nseg) midx = Vector{Float64}(undef, nseg) midy = Vector{Float64}(undef, nseg) midz = Vector{Float64}(undef, nseg) @inbounds for l in 1:nseg - x1 = cs.x[j, k, l]; x2 = cs.x[j, k, l+1] - y1 = cs.y[j, k, l]; y2 = cs.y[j, k, l+1] - z1 = cs.z[j, k, l]; z2 = cs.z[j, k, l+1] - dlx[l] = x2 - x1 - dly[l] = y2 - y1 - dlz[l] = z2 - z1 + x1 = cs.x[j, k, l] + x2 = cs.x[j, k, l+1] + y1 = cs.y[j, k, l] + y2 = cs.y[j, k, l+1] + z1 = cs.z[j, k, l] + z2 = cs.z[j, k, l+1] + dlx[l] = x2 - x1 + dly[l] = y2 - y1 + dlz[l] = z2 - z1 midx[l] = (x1 + x2) * 0.5 midy[l] = (y1 + y2) * 0.5 midz[l] = (z1 + z2) * 0.5 end return PrecomputedSegments(dlx, dly, dlz, midx, midy, midz, - MU0_OVER_4PI * current_nw, nseg) + MU0_OVER_4PI * current_nw, nseg) end """ @@ -74,15 +77,16 @@ end Accumulate the Biot-Savart contribution from one conductor strand onto observation point `i`. Uses midpoint-rule integration: each segment from point `l` to `l+1` contributes: - dB = μ₀/(4π) × current_nw × (dl⃗ × r⃗) / |r|³ +dB = μ₀/(4π) × current_nw × (dl⃗ × r⃗) / |r|³ where `r⃗` is the displacement from the segment midpoint to the observer. ## Arguments -- `Bx`, `By`, `Bz`: pre-allocated output arrays (Cartesian field, Tesla); updated in-place -- `i`: observation point index -- `obs_x/y/z`: observer Cartesian coordinates [m] -- `xs`, `ys`, `zs`: strand point coordinates [nsec], Cartesian [m] -- `current_nw`: effective current = I × nw [A⋅turns] + + - `Bx`, `By`, `Bz`: pre-allocated output arrays (Cartesian field, Tesla); updated in-place + - `i`: observation point index + - `obs_x/y/z`: observer Cartesian coordinates [m] + - `xs`, `ys`, `zs`: strand point coordinates [nsec], Cartesian [m] + - `current_nw`: effective current = I × nw [A⋅turns] """ function accumulate_strand_field!( Bx::AbstractVector{Float64}, @@ -98,7 +102,7 @@ function accumulate_strand_field!( nsec = length(xs) prefactor = MU0_OVER_4PI * current_nw - @inbounds for l in 1:(nsec - 1) + @inbounds for l in 1:(nsec-1) # Segment vector dl⃗ dlx = xs[l+1] - xs[l] dly = ys[l+1] - ys[l] @@ -109,7 +113,7 @@ function accumulate_strand_field!( ry = obs_y - (ys[l] + ys[l+1]) * 0.5 rz = obs_z - (zs[l] + zs[l+1]) * 0.5 - r2 = rx*rx + ry*ry + rz*rz + r2 = rx*rx + ry*ry + rz*rz r2 < BIOT_SAVART_MIN_DIST_SQ && continue # avoid singularity (observer on conductor) inv_r3 = prefactor / (r2 * sqrt(r2)) @@ -146,8 +150,8 @@ cache efficiency. r2 = rx*rx + ry*ry + rz*rz # Guard: zero contribution if observer is on conductor (avoids Inf/NaN) safe_r2 = ifelse(r2 < BIOT_SAVART_MIN_DIST_SQ, one(r2), r2) - scale = ifelse(r2 < BIOT_SAVART_MIN_DIST_SQ, zero(pf), pf) - inv_r3 = scale / (safe_r2 * sqrt(safe_r2)) + scale = ifelse(r2 < BIOT_SAVART_MIN_DIST_SQ, zero(pf), pf) + inv_r3 = scale / (safe_r2 * sqrt(safe_r2)) bx_acc += (seg.dly[l]*rz - seg.dlz[l]*ry) * inv_r3 by_acc += (seg.dlz[l]*rx - seg.dlx[l]*rz) * inv_r3 @@ -172,9 +176,10 @@ Performance: segment vectors and midpoints are pre-computed once outside the observation-point loop, then accessed from contiguous arrays in the inner kernel. ## Arguments -- `B_R`, `B_phi`, `B_Z`: output field arrays [Tesla], length `nobs`; overwritten -- `obs_R`, `obs_phi`, `obs_Z`: observation point cylindrical coordinates [m, rad, m] -- `coil_sets`: conductor geometry and current data + + - `B_R`, `B_phi`, `B_Z`: output field arrays [Tesla], length `nobs`; overwritten + - `obs_R`, `obs_phi`, `obs_Z`: observation point cylindrical coordinates [m, rad, m] + - `coil_sets`: conductor geometry and current data """ function compute_biot_savart_boundary!( B_R::AbstractVector{Float64}, @@ -204,8 +209,8 @@ function compute_biot_savart_boundary!( # Pre-compute sincos for cylindrical ↔ Cartesian conversion (avoids redundant trig) cos_phi = Vector{Float64}(undef, nobs) sin_phi = Vector{Float64}(undef, nobs) - obs_x = Vector{Float64}(undef, nobs) - obs_y = Vector{Float64}(undef, nobs) + obs_x = Vector{Float64}(undef, nobs) + obs_y = Vector{Float64}(undef, nobs) @inbounds for i in 1:nobs sp, cp = sincos(obs_phi[i]) @@ -218,7 +223,9 @@ function compute_biot_savart_boundary!( # Each thread writes exclusively to its own index i — no synchronization needed Threads.@threads for i in 1:nobs @inbounds begin - ox = obs_x[i]; oy = obs_y[i]; oz = obs_Z[i] + ox = obs_x[i] + oy = obs_y[i] + oz = obs_Z[i] bx_total = 0.0 by_total = 0.0 bz_total = 0.0 @@ -233,9 +240,9 @@ function compute_biot_savart_boundary!( # Convert Cartesian → cylindrical in-place cp = cos_phi[i] sp = sin_phi[i] - B_R[i] = bx_total * cp + by_total * sp + B_R[i] = bx_total * cp + by_total * sp B_phi[i] = -bx_total * sp + by_total * cp - B_Z[i] = bz_total + B_Z[i] = bz_total end end end diff --git a/src/ForcingTerms/CoilGeometry.jl b/src/ForcingTerms/CoilGeometry.jl index b2d19ab21..477502927 100644 --- a/src/ForcingTerms/CoilGeometry.jl +++ b/src/ForcingTerms/CoilGeometry.jl @@ -265,7 +265,7 @@ function read_coil_dat(filepath::String) for l in 1:nsec # Skip blank/comment lines between data rows while row <= length(lines) && - (isempty(strip(lines[row])) || startswith(strip(lines[row]), "#")) + (isempty(strip(lines[row])) || startswith(strip(lines[row]), "#")) row += 1 end row > length(lines) && error( @@ -402,10 +402,12 @@ function make_window_pane_standoff(equil; standoff::Real, poloidal_angle::Real, # boundary along the normal is standoff - half*|sin(tilt)| — the tilt tips the legs toward the # surface, while tangential displacement leaves the normal clearance unchanged. clearance = standoff - half * abs(sin(deg2rad(poloidal_tilt))) - clearance > 0 || error("make_window_pane_standoff: coil intersects the plasma boundary " * - "(standoff=$standoff, poloidal_length=$poloidal_length, poloidal_tilt=$poloidal_tilt); " * - "an external coil must lie outside the control surface — increase standoff or reduce " * - "poloidal_length/poloidal_tilt") + clearance > 0 || error( + "make_window_pane_standoff: coil intersects the plasma boundary " * + "(standoff=$standoff, poloidal_length=$poloidal_length, poloidal_tilt=$poloidal_tilt); " * + "an external coil must lie outside the control surface — increase standoff or reduce " * + "poloidal_length/poloidal_tilt" + ) c1 = [Rc - half * uR, Zc - half * uZ] c2 = [Rc + half * uR, Zc + half * uZ] diff --git a/src/ForcingTerms/coil_geometries/jet_ex_mid.dat b/src/ForcingTerms/coil_geometries/jet_ex_mid.dat index ea2549ad3..639e8ca41 100644 --- a/src/ForcingTerms/coil_geometries/jet_ex_mid.dat +++ b/src/ForcingTerms/coil_geometries/jet_ex_mid.dat @@ -1,169 +1,169 @@ - 4 1 42 1.00 - 5.5000e+00 0.0000e+00 3.0900e+00 - 5.4795e+00 4.7404e-01 3.0900e+00 - 5.4183e+00 9.4456e-01 3.0900e+00 - 5.3167e+00 1.4080e+00 3.0900e+00 - 5.1756e+00 1.8611e+00 3.0900e+00 - 4.9959e+00 2.3002e+00 3.0900e+00 - 4.7791e+00 2.7222e+00 3.0900e+00 - 4.5266e+00 3.1240e+00 3.0900e+00 - 4.2405e+00 3.5025e+00 3.0900e+00 - 3.9229e+00 3.8550e+00 3.0900e+00 - 3.5760e+00 4.1788e+00 3.0900e+00 - 3.2025e+00 4.4714e+00 3.0900e+00 - 2.8052e+00 4.7308e+00 3.0900e+00 - 2.3870e+00 4.9550e+00 3.0900e+00 - 1.9511e+00 5.1423e+00 3.0900e+00 - 1.5006e+00 5.2913e+00 3.0900e+00 - 1.0390e+00 5.4010e+00 3.0900e+00 - 5.6960e-01 5.4704e+00 3.0900e+00 - 9.5988e-02 5.4992e+00 3.0900e+00 - 9.5988e-02 5.4992e+00 3.0900e+00 - 9.5988e-02 5.4992e+00 1.5700e+00 - 9.5988e-02 5.4992e+00 5.0000e-02 - 9.5988e-02 5.4992e+00 -1.4700e+00 - 9.5988e-02 5.4992e+00 -2.9900e+00 - 7.0430e-01 5.4547e+00 -2.9900e+00 - 1.3039e+00 5.3432e+00 -2.9900e+00 - 1.8876e+00 5.1660e+00 -2.9900e+00 - 2.4479e+00 4.9252e+00 -2.9900e+00 - 2.9782e+00 4.6239e+00 -2.9900e+00 - 3.4719e+00 4.2657e+00 -2.9900e+00 - 3.9229e+00 3.8550e+00 -2.9900e+00 - 4.3256e+00 3.3969e+00 -2.9900e+00 - 4.6751e+00 2.8971e+00 -2.9900e+00 - 4.9672e+00 2.3616e+00 -2.9900e+00 - 5.1981e+00 1.7971e+00 -2.9900e+00 - 5.3651e+00 1.2105e+00 -2.9900e+00 - 5.4662e+00 6.0899e-01 -2.9900e+00 - 5.5000e+00 0.0000e+00 -2.9900e+00 - 5.5000e+00 0.0000e+00 -1.4700e+00 - 5.5000e+00 0.0000e+00 5.0000e-02 - 5.5000e+00 0.0000e+00 1.5700e+00 - 5.5000e+00 0.0000e+00 3.0900e+00 - 3.3678e-16 5.5000e+00 3.0900e+00 - -4.7404e-01 5.4795e+00 3.0900e+00 - -9.4456e-01 5.4183e+00 3.0900e+00 - -1.4080e+00 5.3167e+00 3.0900e+00 - -1.8611e+00 5.1756e+00 3.0900e+00 - -2.3002e+00 4.9959e+00 3.0900e+00 - -2.7222e+00 4.7791e+00 3.0900e+00 - -3.1240e+00 4.5266e+00 3.0900e+00 - -3.5025e+00 4.2405e+00 3.0900e+00 - -3.8550e+00 3.9229e+00 3.0900e+00 - -4.1788e+00 3.5760e+00 3.0900e+00 - -4.4714e+00 3.2025e+00 3.0900e+00 - -4.7308e+00 2.8052e+00 3.0900e+00 - -4.9550e+00 2.3870e+00 3.0900e+00 - -5.1423e+00 1.9511e+00 3.0900e+00 - -5.2913e+00 1.5006e+00 3.0900e+00 - -5.4010e+00 1.0390e+00 3.0900e+00 - -5.4704e+00 5.6960e-01 3.0900e+00 - -5.4992e+00 9.5988e-02 3.0900e+00 - -5.4992e+00 9.5988e-02 3.0900e+00 - -5.4992e+00 9.5988e-02 1.5700e+00 - -5.4992e+00 9.5988e-02 5.0000e-02 - -5.4992e+00 9.5988e-02 -1.4700e+00 - -5.4992e+00 9.5988e-02 -2.9900e+00 - -5.4547e+00 7.0430e-01 -2.9900e+00 - -5.3432e+00 1.3039e+00 -2.9900e+00 - -5.1660e+00 1.8876e+00 -2.9900e+00 - -4.9252e+00 2.4479e+00 -2.9900e+00 - -4.6239e+00 2.9782e+00 -2.9900e+00 - -4.2657e+00 3.4719e+00 -2.9900e+00 - -3.8550e+00 3.9229e+00 -2.9900e+00 - -3.3969e+00 4.3256e+00 -2.9900e+00 - -2.8971e+00 4.6751e+00 -2.9900e+00 - -2.3616e+00 4.9672e+00 -2.9900e+00 - -1.7971e+00 5.1981e+00 -2.9900e+00 - -1.2105e+00 5.3651e+00 -2.9900e+00 - -6.0899e-01 5.4662e+00 -2.9900e+00 - 3.3678e-16 5.5000e+00 -2.9900e+00 - 3.3678e-16 5.5000e+00 -1.4700e+00 - 3.3678e-16 5.5000e+00 5.0000e-02 - 3.3678e-16 5.5000e+00 1.5700e+00 - 3.3678e-16 5.5000e+00 3.0900e+00 - -5.5000e+00 6.7356e-16 3.0900e+00 - -5.4795e+00 -4.7404e-01 3.0900e+00 - -5.4183e+00 -9.4456e-01 3.0900e+00 - -5.3167e+00 -1.4080e+00 3.0900e+00 - -5.1756e+00 -1.8611e+00 3.0900e+00 - -4.9959e+00 -2.3002e+00 3.0900e+00 - -4.7791e+00 -2.7222e+00 3.0900e+00 - -4.5266e+00 -3.1240e+00 3.0900e+00 - -4.2405e+00 -3.5025e+00 3.0900e+00 - -3.9229e+00 -3.8550e+00 3.0900e+00 - -3.5760e+00 -4.1788e+00 3.0900e+00 - -3.2025e+00 -4.4714e+00 3.0900e+00 - -2.8052e+00 -4.7308e+00 3.0900e+00 - -2.3870e+00 -4.9550e+00 3.0900e+00 - -1.9511e+00 -5.1423e+00 3.0900e+00 - -1.5006e+00 -5.2913e+00 3.0900e+00 - -1.0390e+00 -5.4010e+00 3.0900e+00 - -5.6960e-01 -5.4704e+00 3.0900e+00 - -9.5988e-02 -5.4992e+00 3.0900e+00 - -9.5988e-02 -5.4992e+00 3.0900e+00 - -9.5988e-02 -5.4992e+00 1.5700e+00 - -9.5988e-02 -5.4992e+00 5.0000e-02 - -9.5988e-02 -5.4992e+00 -1.4700e+00 - -9.5988e-02 -5.4992e+00 -2.9900e+00 - -7.0430e-01 -5.4547e+00 -2.9900e+00 - -1.3039e+00 -5.3432e+00 -2.9900e+00 - -1.8876e+00 -5.1660e+00 -2.9900e+00 - -2.4479e+00 -4.9252e+00 -2.9900e+00 - -2.9782e+00 -4.6239e+00 -2.9900e+00 - -3.4719e+00 -4.2657e+00 -2.9900e+00 - -3.9229e+00 -3.8550e+00 -2.9900e+00 - -4.3256e+00 -3.3969e+00 -2.9900e+00 - -4.6751e+00 -2.8971e+00 -2.9900e+00 - -4.9672e+00 -2.3616e+00 -2.9900e+00 - -5.1981e+00 -1.7971e+00 -2.9900e+00 - -5.3651e+00 -1.2105e+00 -2.9900e+00 - -5.4662e+00 -6.0899e-01 -2.9900e+00 - -5.5000e+00 6.7356e-16 -2.9900e+00 - -5.5000e+00 6.7356e-16 -1.4700e+00 - -5.5000e+00 6.7356e-16 5.0000e-02 - -5.5000e+00 6.7356e-16 1.5700e+00 - -5.5000e+00 6.7356e-16 3.0900e+00 - -1.0103e-15 -5.5000e+00 3.0900e+00 - 4.7404e-01 -5.4795e+00 3.0900e+00 - 9.4456e-01 -5.4183e+00 3.0900e+00 - 1.4080e+00 -5.3167e+00 3.0900e+00 - 1.8611e+00 -5.1756e+00 3.0900e+00 - 2.3002e+00 -4.9959e+00 3.0900e+00 - 2.7222e+00 -4.7791e+00 3.0900e+00 - 3.1240e+00 -4.5266e+00 3.0900e+00 - 3.5025e+00 -4.2405e+00 3.0900e+00 - 3.8550e+00 -3.9229e+00 3.0900e+00 - 4.1788e+00 -3.5760e+00 3.0900e+00 - 4.4714e+00 -3.2025e+00 3.0900e+00 - 4.7308e+00 -2.8052e+00 3.0900e+00 - 4.9550e+00 -2.3870e+00 3.0900e+00 - 5.1423e+00 -1.9511e+00 3.0900e+00 - 5.2913e+00 -1.5006e+00 3.0900e+00 - 5.4010e+00 -1.0390e+00 3.0900e+00 - 5.4704e+00 -5.6960e-01 3.0900e+00 - 5.4992e+00 -9.5988e-02 3.0900e+00 - 5.4992e+00 -9.5988e-02 3.0900e+00 - 5.4992e+00 -9.5988e-02 1.5700e+00 - 5.4992e+00 -9.5988e-02 5.0000e-02 - 5.4992e+00 -9.5988e-02 -1.4700e+00 - 5.4992e+00 -9.5988e-02 -2.9900e+00 - 5.4547e+00 -7.0430e-01 -2.9900e+00 - 5.3432e+00 -1.3039e+00 -2.9900e+00 - 5.1660e+00 -1.8876e+00 -2.9900e+00 - 4.9252e+00 -2.4479e+00 -2.9900e+00 - 4.6239e+00 -2.9782e+00 -2.9900e+00 - 4.2657e+00 -3.4719e+00 -2.9900e+00 - 3.8550e+00 -3.9229e+00 -2.9900e+00 - 3.3969e+00 -4.3256e+00 -2.9900e+00 - 2.8971e+00 -4.6751e+00 -2.9900e+00 - 2.3616e+00 -4.9672e+00 -2.9900e+00 - 1.7971e+00 -5.1981e+00 -2.9900e+00 - 1.2105e+00 -5.3651e+00 -2.9900e+00 - 6.0899e-01 -5.4662e+00 -2.9900e+00 - -1.0103e-15 -5.5000e+00 -2.9900e+00 - -1.0103e-15 -5.5000e+00 -1.4700e+00 - -1.0103e-15 -5.5000e+00 5.0000e-02 - -1.0103e-15 -5.5000e+00 1.5700e+00 - -1.0103e-15 -5.5000e+00 3.0900e+00 + 4 1 42 1.00 + 5.5000e+00 0.0000e+00 3.0900e+00 + 5.4795e+00 4.7404e-01 3.0900e+00 + 5.4183e+00 9.4456e-01 3.0900e+00 + 5.3167e+00 1.4080e+00 3.0900e+00 + 5.1756e+00 1.8611e+00 3.0900e+00 + 4.9959e+00 2.3002e+00 3.0900e+00 + 4.7791e+00 2.7222e+00 3.0900e+00 + 4.5266e+00 3.1240e+00 3.0900e+00 + 4.2405e+00 3.5025e+00 3.0900e+00 + 3.9229e+00 3.8550e+00 3.0900e+00 + 3.5760e+00 4.1788e+00 3.0900e+00 + 3.2025e+00 4.4714e+00 3.0900e+00 + 2.8052e+00 4.7308e+00 3.0900e+00 + 2.3870e+00 4.9550e+00 3.0900e+00 + 1.9511e+00 5.1423e+00 3.0900e+00 + 1.5006e+00 5.2913e+00 3.0900e+00 + 1.0390e+00 5.4010e+00 3.0900e+00 + 5.6960e-01 5.4704e+00 3.0900e+00 + 9.5988e-02 5.4992e+00 3.0900e+00 + 9.5988e-02 5.4992e+00 3.0900e+00 + 9.5988e-02 5.4992e+00 1.5700e+00 + 9.5988e-02 5.4992e+00 5.0000e-02 + 9.5988e-02 5.4992e+00 -1.4700e+00 + 9.5988e-02 5.4992e+00 -2.9900e+00 + 7.0430e-01 5.4547e+00 -2.9900e+00 + 1.3039e+00 5.3432e+00 -2.9900e+00 + 1.8876e+00 5.1660e+00 -2.9900e+00 + 2.4479e+00 4.9252e+00 -2.9900e+00 + 2.9782e+00 4.6239e+00 -2.9900e+00 + 3.4719e+00 4.2657e+00 -2.9900e+00 + 3.9229e+00 3.8550e+00 -2.9900e+00 + 4.3256e+00 3.3969e+00 -2.9900e+00 + 4.6751e+00 2.8971e+00 -2.9900e+00 + 4.9672e+00 2.3616e+00 -2.9900e+00 + 5.1981e+00 1.7971e+00 -2.9900e+00 + 5.3651e+00 1.2105e+00 -2.9900e+00 + 5.4662e+00 6.0899e-01 -2.9900e+00 + 5.5000e+00 0.0000e+00 -2.9900e+00 + 5.5000e+00 0.0000e+00 -1.4700e+00 + 5.5000e+00 0.0000e+00 5.0000e-02 + 5.5000e+00 0.0000e+00 1.5700e+00 + 5.5000e+00 0.0000e+00 3.0900e+00 + 3.3678e-16 5.5000e+00 3.0900e+00 + -4.7404e-01 5.4795e+00 3.0900e+00 + -9.4456e-01 5.4183e+00 3.0900e+00 + -1.4080e+00 5.3167e+00 3.0900e+00 + -1.8611e+00 5.1756e+00 3.0900e+00 + -2.3002e+00 4.9959e+00 3.0900e+00 + -2.7222e+00 4.7791e+00 3.0900e+00 + -3.1240e+00 4.5266e+00 3.0900e+00 + -3.5025e+00 4.2405e+00 3.0900e+00 + -3.8550e+00 3.9229e+00 3.0900e+00 + -4.1788e+00 3.5760e+00 3.0900e+00 + -4.4714e+00 3.2025e+00 3.0900e+00 + -4.7308e+00 2.8052e+00 3.0900e+00 + -4.9550e+00 2.3870e+00 3.0900e+00 + -5.1423e+00 1.9511e+00 3.0900e+00 + -5.2913e+00 1.5006e+00 3.0900e+00 + -5.4010e+00 1.0390e+00 3.0900e+00 + -5.4704e+00 5.6960e-01 3.0900e+00 + -5.4992e+00 9.5988e-02 3.0900e+00 + -5.4992e+00 9.5988e-02 3.0900e+00 + -5.4992e+00 9.5988e-02 1.5700e+00 + -5.4992e+00 9.5988e-02 5.0000e-02 + -5.4992e+00 9.5988e-02 -1.4700e+00 + -5.4992e+00 9.5988e-02 -2.9900e+00 + -5.4547e+00 7.0430e-01 -2.9900e+00 + -5.3432e+00 1.3039e+00 -2.9900e+00 + -5.1660e+00 1.8876e+00 -2.9900e+00 + -4.9252e+00 2.4479e+00 -2.9900e+00 + -4.6239e+00 2.9782e+00 -2.9900e+00 + -4.2657e+00 3.4719e+00 -2.9900e+00 + -3.8550e+00 3.9229e+00 -2.9900e+00 + -3.3969e+00 4.3256e+00 -2.9900e+00 + -2.8971e+00 4.6751e+00 -2.9900e+00 + -2.3616e+00 4.9672e+00 -2.9900e+00 + -1.7971e+00 5.1981e+00 -2.9900e+00 + -1.2105e+00 5.3651e+00 -2.9900e+00 + -6.0899e-01 5.4662e+00 -2.9900e+00 + 3.3678e-16 5.5000e+00 -2.9900e+00 + 3.3678e-16 5.5000e+00 -1.4700e+00 + 3.3678e-16 5.5000e+00 5.0000e-02 + 3.3678e-16 5.5000e+00 1.5700e+00 + 3.3678e-16 5.5000e+00 3.0900e+00 + -5.5000e+00 6.7356e-16 3.0900e+00 + -5.4795e+00 -4.7404e-01 3.0900e+00 + -5.4183e+00 -9.4456e-01 3.0900e+00 + -5.3167e+00 -1.4080e+00 3.0900e+00 + -5.1756e+00 -1.8611e+00 3.0900e+00 + -4.9959e+00 -2.3002e+00 3.0900e+00 + -4.7791e+00 -2.7222e+00 3.0900e+00 + -4.5266e+00 -3.1240e+00 3.0900e+00 + -4.2405e+00 -3.5025e+00 3.0900e+00 + -3.9229e+00 -3.8550e+00 3.0900e+00 + -3.5760e+00 -4.1788e+00 3.0900e+00 + -3.2025e+00 -4.4714e+00 3.0900e+00 + -2.8052e+00 -4.7308e+00 3.0900e+00 + -2.3870e+00 -4.9550e+00 3.0900e+00 + -1.9511e+00 -5.1423e+00 3.0900e+00 + -1.5006e+00 -5.2913e+00 3.0900e+00 + -1.0390e+00 -5.4010e+00 3.0900e+00 + -5.6960e-01 -5.4704e+00 3.0900e+00 + -9.5988e-02 -5.4992e+00 3.0900e+00 + -9.5988e-02 -5.4992e+00 3.0900e+00 + -9.5988e-02 -5.4992e+00 1.5700e+00 + -9.5988e-02 -5.4992e+00 5.0000e-02 + -9.5988e-02 -5.4992e+00 -1.4700e+00 + -9.5988e-02 -5.4992e+00 -2.9900e+00 + -7.0430e-01 -5.4547e+00 -2.9900e+00 + -1.3039e+00 -5.3432e+00 -2.9900e+00 + -1.8876e+00 -5.1660e+00 -2.9900e+00 + -2.4479e+00 -4.9252e+00 -2.9900e+00 + -2.9782e+00 -4.6239e+00 -2.9900e+00 + -3.4719e+00 -4.2657e+00 -2.9900e+00 + -3.9229e+00 -3.8550e+00 -2.9900e+00 + -4.3256e+00 -3.3969e+00 -2.9900e+00 + -4.6751e+00 -2.8971e+00 -2.9900e+00 + -4.9672e+00 -2.3616e+00 -2.9900e+00 + -5.1981e+00 -1.7971e+00 -2.9900e+00 + -5.3651e+00 -1.2105e+00 -2.9900e+00 + -5.4662e+00 -6.0899e-01 -2.9900e+00 + -5.5000e+00 6.7356e-16 -2.9900e+00 + -5.5000e+00 6.7356e-16 -1.4700e+00 + -5.5000e+00 6.7356e-16 5.0000e-02 + -5.5000e+00 6.7356e-16 1.5700e+00 + -5.5000e+00 6.7356e-16 3.0900e+00 + -1.0103e-15 -5.5000e+00 3.0900e+00 + 4.7404e-01 -5.4795e+00 3.0900e+00 + 9.4456e-01 -5.4183e+00 3.0900e+00 + 1.4080e+00 -5.3167e+00 3.0900e+00 + 1.8611e+00 -5.1756e+00 3.0900e+00 + 2.3002e+00 -4.9959e+00 3.0900e+00 + 2.7222e+00 -4.7791e+00 3.0900e+00 + 3.1240e+00 -4.5266e+00 3.0900e+00 + 3.5025e+00 -4.2405e+00 3.0900e+00 + 3.8550e+00 -3.9229e+00 3.0900e+00 + 4.1788e+00 -3.5760e+00 3.0900e+00 + 4.4714e+00 -3.2025e+00 3.0900e+00 + 4.7308e+00 -2.8052e+00 3.0900e+00 + 4.9550e+00 -2.3870e+00 3.0900e+00 + 5.1423e+00 -1.9511e+00 3.0900e+00 + 5.2913e+00 -1.5006e+00 3.0900e+00 + 5.4010e+00 -1.0390e+00 3.0900e+00 + 5.4704e+00 -5.6960e-01 3.0900e+00 + 5.4992e+00 -9.5988e-02 3.0900e+00 + 5.4992e+00 -9.5988e-02 3.0900e+00 + 5.4992e+00 -9.5988e-02 1.5700e+00 + 5.4992e+00 -9.5988e-02 5.0000e-02 + 5.4992e+00 -9.5988e-02 -1.4700e+00 + 5.4992e+00 -9.5988e-02 -2.9900e+00 + 5.4547e+00 -7.0430e-01 -2.9900e+00 + 5.3432e+00 -1.3039e+00 -2.9900e+00 + 5.1660e+00 -1.8876e+00 -2.9900e+00 + 4.9252e+00 -2.4479e+00 -2.9900e+00 + 4.6239e+00 -2.9782e+00 -2.9900e+00 + 4.2657e+00 -3.4719e+00 -2.9900e+00 + 3.8550e+00 -3.9229e+00 -2.9900e+00 + 3.3969e+00 -4.3256e+00 -2.9900e+00 + 2.8971e+00 -4.6751e+00 -2.9900e+00 + 2.3616e+00 -4.9672e+00 -2.9900e+00 + 1.7971e+00 -5.1981e+00 -2.9900e+00 + 1.2105e+00 -5.3651e+00 -2.9900e+00 + 6.0899e-01 -5.4662e+00 -2.9900e+00 + -1.0103e-15 -5.5000e+00 -2.9900e+00 + -1.0103e-15 -5.5000e+00 -1.4700e+00 + -1.0103e-15 -5.5000e+00 5.0000e-02 + -1.0103e-15 -5.5000e+00 1.5700e+00 + -1.0103e-15 -5.5000e+00 3.0900e+00 diff --git a/src/ForcingTerms/coil_geometries/jtext_l.dat b/src/ForcingTerms/coil_geometries/jtext_l.dat index b744bedd8..476b55451 100644 --- a/src/ForcingTerms/coil_geometries/jtext_l.dat +++ b/src/ForcingTerms/coil_geometries/jtext_l.dat @@ -1,81 +1,81 @@ - 4 1 20 1.00 - 1.2000e+00 1.6000e-02 -3.9800e-01 - 1.2000e+00 1.6000e-02 -3.3300e-01 - 1.2000e+00 2.5370e-02 -3.1000e-01 - 1.2000e+00 4.8000e-02 -3.0100e-01 - 1.2000e+00 1.3200e-01 -3.0100e-01 - 1.1880e+00 1.5800e-01 -3.0100e-01 - 1.1620e+00 1.6300e-01 -3.0100e-01 - 7.9400e-01 9.0000e-02 -3.0100e-01 - 7.7500e-01 7.9000e-02 -3.0100e-01 - 7.6800e-01 5.8000e-02 -3.0100e-01 - 7.6800e-01 -6.2000e-02 -3.0100e-01 - 7.7500e-01 -8.3000e-02 -3.0100e-01 - 7.9500e-01 -9.4000e-02 -3.0100e-01 - 1.1620e+00 -1.6700e-01 -3.0100e-01 - 1.1880e+00 -1.6000e-01 -3.0100e-01 - 1.2000e+00 -1.3500e-01 -3.0100e-01 - 1.2000e+00 -5.0000e-02 -3.0100e-01 - 1.2000e+00 -2.5370e-02 -3.1000e-01 - 1.2000e+00 -1.6000e-02 -3.3300e-01 - 1.2000e+00 -1.6000e-02 -3.9800e-01 - 1.6000e-02 1.2000e+00 -3.9800e-01 - 1.6000e-02 1.2000e+00 -3.3300e-01 - 2.5370e-02 1.2000e+00 -3.1000e-01 - 4.8000e-02 1.2000e+00 -3.0100e-01 - 1.3200e-01 1.2000e+00 -3.0100e-01 - 1.5800e-01 1.1880e+00 -3.0100e-01 - 1.6300e-01 1.1620e+00 -3.0100e-01 - 9.0000e-02 7.9400e-01 -3.0100e-01 - 7.9000e-02 7.7500e-01 -3.0100e-01 - 5.8000e-02 7.6800e-01 -3.0100e-01 - -6.2000e-02 7.6800e-01 -3.0100e-01 - -8.3000e-02 7.7500e-01 -3.0100e-01 - -9.4000e-02 7.9500e-01 -3.0100e-01 - -1.6700e-01 1.1620e+00 -3.0100e-01 - -1.6000e-01 1.1880e+00 -3.0100e-01 - -1.3500e-01 1.2000e+00 -3.0100e-01 - -5.0000e-02 1.2000e+00 -3.0100e-01 - -2.5370e-02 1.2000e+00 -3.1000e-01 - -1.6000e-02 1.2000e+00 -3.3300e-01 - -1.6000e-02 1.2000e+00 -3.9800e-01 - -7.7650e-01 1.6000e-02 -3.9800e-01 - -7.7650e-01 1.6000e-02 -3.3300e-01 - -7.7650e-01 2.5370e-02 -3.1000e-01 - -7.7650e-01 4.8000e-02 -3.0100e-01 - -7.7650e-01 6.1000e-02 -3.0100e-01 - -7.8350e-01 8.2000e-02 -3.0100e-01 - -8.0250e-01 9.3000e-02 -3.0100e-01 - -1.2015e+00 1.7100e-01 -3.0100e-01 - -1.2275e+00 1.6500e-01 -3.0100e-01 - -1.2395e+00 1.4100e-01 -3.0100e-01 - -1.2395e+00 -1.4100e-01 -3.0100e-01 - -1.2275e+00 -1.6600e-01 -3.0100e-01 - -1.2015e+00 -1.7200e-01 -3.0100e-01 - -8.0250e-01 -9.3000e-02 -3.0100e-01 - -7.8350e-01 -8.2000e-02 -3.0100e-01 - -7.7650e-01 -6.2000e-02 -3.0100e-01 - -7.7650e-01 -4.9000e-02 -3.0100e-01 - -7.7650e-01 -2.5370e-02 -3.1000e-01 - -7.7650e-01 -1.6000e-02 -3.3300e-01 - -7.7650e-01 -1.6000e-02 -3.9800e-01 - 1.6000e-02 -7.7650e-01 -3.9800e-01 - 1.6000e-02 -7.7650e-01 -3.3300e-01 - 2.5370e-02 -7.7650e-01 -3.1000e-01 - 4.8000e-02 -7.7650e-01 -3.0100e-01 - 6.1000e-02 -7.7650e-01 -3.0100e-01 - 8.2000e-02 -7.8350e-01 -3.0100e-01 - 9.3000e-02 -8.0250e-01 -3.0100e-01 - 1.7100e-01 -1.2015e+00 -3.0100e-01 - 1.6500e-01 -1.2275e+00 -3.0100e-01 - 1.4100e-01 -1.2395e+00 -3.0100e-01 - -1.4100e-01 -1.2395e+00 -3.0100e-01 - -1.6600e-01 -1.2275e+00 -3.0100e-01 - -1.7200e-01 -1.2015e+00 -3.0100e-01 - -9.3000e-02 -8.0250e-01 -3.0100e-01 - -8.2000e-02 -7.8350e-01 -3.0100e-01 - -6.2000e-02 -7.7650e-01 -3.0100e-01 - -4.9000e-02 -7.7650e-01 -3.0100e-01 - -2.5370e-02 -7.7650e-01 -3.1000e-01 - -1.6000e-02 -7.7650e-01 -3.3300e-01 - -1.6000e-02 -7.7650e-01 -3.9800e-01 + 4 1 20 1.00 + 1.2000e+00 1.6000e-02 -3.9800e-01 + 1.2000e+00 1.6000e-02 -3.3300e-01 + 1.2000e+00 2.5370e-02 -3.1000e-01 + 1.2000e+00 4.8000e-02 -3.0100e-01 + 1.2000e+00 1.3200e-01 -3.0100e-01 + 1.1880e+00 1.5800e-01 -3.0100e-01 + 1.1620e+00 1.6300e-01 -3.0100e-01 + 7.9400e-01 9.0000e-02 -3.0100e-01 + 7.7500e-01 7.9000e-02 -3.0100e-01 + 7.6800e-01 5.8000e-02 -3.0100e-01 + 7.6800e-01 -6.2000e-02 -3.0100e-01 + 7.7500e-01 -8.3000e-02 -3.0100e-01 + 7.9500e-01 -9.4000e-02 -3.0100e-01 + 1.1620e+00 -1.6700e-01 -3.0100e-01 + 1.1880e+00 -1.6000e-01 -3.0100e-01 + 1.2000e+00 -1.3500e-01 -3.0100e-01 + 1.2000e+00 -5.0000e-02 -3.0100e-01 + 1.2000e+00 -2.5370e-02 -3.1000e-01 + 1.2000e+00 -1.6000e-02 -3.3300e-01 + 1.2000e+00 -1.6000e-02 -3.9800e-01 + 1.6000e-02 1.2000e+00 -3.9800e-01 + 1.6000e-02 1.2000e+00 -3.3300e-01 + 2.5370e-02 1.2000e+00 -3.1000e-01 + 4.8000e-02 1.2000e+00 -3.0100e-01 + 1.3200e-01 1.2000e+00 -3.0100e-01 + 1.5800e-01 1.1880e+00 -3.0100e-01 + 1.6300e-01 1.1620e+00 -3.0100e-01 + 9.0000e-02 7.9400e-01 -3.0100e-01 + 7.9000e-02 7.7500e-01 -3.0100e-01 + 5.8000e-02 7.6800e-01 -3.0100e-01 + -6.2000e-02 7.6800e-01 -3.0100e-01 + -8.3000e-02 7.7500e-01 -3.0100e-01 + -9.4000e-02 7.9500e-01 -3.0100e-01 + -1.6700e-01 1.1620e+00 -3.0100e-01 + -1.6000e-01 1.1880e+00 -3.0100e-01 + -1.3500e-01 1.2000e+00 -3.0100e-01 + -5.0000e-02 1.2000e+00 -3.0100e-01 + -2.5370e-02 1.2000e+00 -3.1000e-01 + -1.6000e-02 1.2000e+00 -3.3300e-01 + -1.6000e-02 1.2000e+00 -3.9800e-01 + -7.7650e-01 1.6000e-02 -3.9800e-01 + -7.7650e-01 1.6000e-02 -3.3300e-01 + -7.7650e-01 2.5370e-02 -3.1000e-01 + -7.7650e-01 4.8000e-02 -3.0100e-01 + -7.7650e-01 6.1000e-02 -3.0100e-01 + -7.8350e-01 8.2000e-02 -3.0100e-01 + -8.0250e-01 9.3000e-02 -3.0100e-01 + -1.2015e+00 1.7100e-01 -3.0100e-01 + -1.2275e+00 1.6500e-01 -3.0100e-01 + -1.2395e+00 1.4100e-01 -3.0100e-01 + -1.2395e+00 -1.4100e-01 -3.0100e-01 + -1.2275e+00 -1.6600e-01 -3.0100e-01 + -1.2015e+00 -1.7200e-01 -3.0100e-01 + -8.0250e-01 -9.3000e-02 -3.0100e-01 + -7.8350e-01 -8.2000e-02 -3.0100e-01 + -7.7650e-01 -6.2000e-02 -3.0100e-01 + -7.7650e-01 -4.9000e-02 -3.0100e-01 + -7.7650e-01 -2.5370e-02 -3.1000e-01 + -7.7650e-01 -1.6000e-02 -3.3300e-01 + -7.7650e-01 -1.6000e-02 -3.9800e-01 + 1.6000e-02 -7.7650e-01 -3.9800e-01 + 1.6000e-02 -7.7650e-01 -3.3300e-01 + 2.5370e-02 -7.7650e-01 -3.1000e-01 + 4.8000e-02 -7.7650e-01 -3.0100e-01 + 6.1000e-02 -7.7650e-01 -3.0100e-01 + 8.2000e-02 -7.8350e-01 -3.0100e-01 + 9.3000e-02 -8.0250e-01 -3.0100e-01 + 1.7100e-01 -1.2015e+00 -3.0100e-01 + 1.6500e-01 -1.2275e+00 -3.0100e-01 + 1.4100e-01 -1.2395e+00 -3.0100e-01 + -1.4100e-01 -1.2395e+00 -3.0100e-01 + -1.6600e-01 -1.2275e+00 -3.0100e-01 + -1.7200e-01 -1.2015e+00 -3.0100e-01 + -9.3000e-02 -8.0250e-01 -3.0100e-01 + -8.2000e-02 -7.8350e-01 -3.0100e-01 + -6.2000e-02 -7.7650e-01 -3.0100e-01 + -4.9000e-02 -7.7650e-01 -3.0100e-01 + -2.5370e-02 -7.7650e-01 -3.1000e-01 + -1.6000e-02 -7.7650e-01 -3.3300e-01 + -1.6000e-02 -7.7650e-01 -3.9800e-01 diff --git a/src/ForcingTerms/coil_geometries/jtext_m.dat b/src/ForcingTerms/coil_geometries/jtext_m.dat index f211a2d1e..9defc821f 100644 --- a/src/ForcingTerms/coil_geometries/jtext_m.dat +++ b/src/ForcingTerms/coil_geometries/jtext_m.dat @@ -1,81 +1,81 @@ - 4 1 20 1.00 - 1.3300e+00 1.6000e-02 3.5600e-01 - 1.2830e+00 1.6000e-02 2.6500e-01 - 1.3065e+00 2.5370e-02 2.4300e-01 - 1.3300e+00 4.8000e-02 2.1100e-01 - 1.3300e+00 1.3200e-01 2.1100e-01 - 1.3300e+00 1.5800e-01 2.0200e-01 - 1.3300e+00 1.6300e-01 1.7900e-01 - 1.3300e+00 9.0000e-02 -2.0600e-01 - 1.3300e+00 7.9000e-02 -2.2900e-01 - 1.3300e+00 5.8000e-02 -2.3800e-01 - 1.3300e+00 -6.2000e-02 -2.3800e-01 - 1.3300e+00 -8.3000e-02 -2.2900e-01 - 1.3300e+00 -9.4000e-02 -2.0600e-01 - 1.3300e+00 -1.6700e-01 1.7900e-01 - 1.3300e+00 -1.6000e-01 2.0200e-01 - 1.3300e+00 -1.3500e-01 2.1100e-01 - 1.3300e+00 -5.0000e-02 2.1100e-01 - 1.3065e+00 -2.5370e-02 2.4300e-01 - 1.2830e+00 -1.6000e-02 2.6500e-01 - 1.3300e+00 -1.6000e-02 3.5600e-01 - -8.7000e-02 1.2000e+00 -3.5600e-01 - -8.7000e-02 1.2000e+00 -2.6500e-01 - -7.1000e-02 1.2000e+00 -2.4300e-01 - -5.5000e-02 1.2000e+00 -2.1100e-01 - 1.6900e-01 1.2000e+00 -2.1100e-01 - 1.9100e-01 1.1880e+00 -2.0200e-01 - 2.0100e-01 1.1620e+00 -1.7900e-01 - 2.0100e-01 7.9400e-01 2.0600e-01 - 1.9100e-01 7.7500e-01 2.2900e-01 - 1.6900e-01 7.6800e-01 2.3800e-01 - -1.6800e-01 7.6800e-01 2.3800e-01 - -1.9100e-01 7.7500e-01 2.2900e-01 - -2.0000e-01 7.9500e-01 2.0600e-01 - -2.0000e-01 1.1620e+00 -1.7900e-01 - -1.9100e-01 1.1880e+00 -2.0200e-01 - -1.6800e-01 1.2000e+00 -2.1100e-01 - -1.5100e-01 1.2000e+00 -2.1100e-01 - -1.3500e-01 1.2000e+00 -2.4300e-01 - -1.1900e-01 1.2000e+00 -2.6500e-01 - -1.1900e-01 1.2000e+00 -3.5600e-01 - -1.3300e+00 1.6000e-02 3.5600e-01 - -1.2830e+00 1.6000e-02 2.6500e-01 - -1.3065e+00 2.5370e-02 2.4300e-01 - -1.3300e+00 4.8000e-02 2.1100e-01 - -1.3300e+00 6.1000e-02 2.1100e-01 - -1.3300e+00 8.2000e-02 2.0200e-01 - -1.3300e+00 9.3000e-02 1.7900e-01 - -1.3300e+00 1.7100e-01 -2.0600e-01 - -1.3300e+00 1.6500e-01 -2.2900e-01 - -1.3300e+00 1.4100e-01 -2.3800e-01 - -1.3300e+00 -1.4100e-01 -2.3800e-01 - -1.3300e+00 -1.6600e-01 -2.2900e-01 - -1.3300e+00 -1.7200e-01 -2.0600e-01 - -1.3300e+00 -9.3000e-02 1.7900e-01 - -1.3300e+00 -8.2000e-02 2.0200e-01 - -1.3300e+00 -6.2000e-02 2.1100e-01 - -1.3300e+00 -4.9000e-02 2.1100e-01 - -1.3065e+00 -2.5370e-02 2.4300e-01 - -1.2830e+00 -1.6000e-02 2.6500e-01 - -1.3300e+00 -1.6000e-02 3.5600e-01 - 8.7000e-02 -7.7650e-01 -3.5600e-01 - 8.7000e-02 -7.7650e-01 -2.6500e-01 - 7.1000e-02 -7.7650e-01 -2.4300e-01 - 5.5000e-02 -7.7650e-01 -2.1100e-01 - 5.5000e-02 -7.7650e-01 -2.1100e-01 - 3.2600e-02 -7.8350e-01 -2.0200e-01 - 2.2600e-02 -8.0250e-01 -1.7900e-01 - 2.2600e-02 -1.2015e+00 2.0600e-01 - 3.2600e-02 -1.2275e+00 2.2900e-01 - 5.4600e-02 -1.2395e+00 2.3800e-01 - 1.6800e-01 -1.2395e+00 2.3800e-01 - 1.9100e-01 -1.2275e+00 2.2900e-01 - 2.0000e-01 -1.2015e+00 2.0600e-01 - 2.0000e-01 -8.0250e-01 -1.7900e-01 - 1.9100e-01 -7.8350e-01 -2.0200e-01 - 1.6800e-01 -7.7650e-01 -2.1100e-01 - 1.5100e-01 -7.7650e-01 -2.1100e-01 - 1.3500e-01 -7.7650e-01 -2.4300e-01 - 1.1900e-01 -7.7650e-01 -2.6500e-01 - 1.1900e-01 -7.7650e-01 -3.5600e-01 + 4 1 20 1.00 + 1.3300e+00 1.6000e-02 3.5600e-01 + 1.2830e+00 1.6000e-02 2.6500e-01 + 1.3065e+00 2.5370e-02 2.4300e-01 + 1.3300e+00 4.8000e-02 2.1100e-01 + 1.3300e+00 1.3200e-01 2.1100e-01 + 1.3300e+00 1.5800e-01 2.0200e-01 + 1.3300e+00 1.6300e-01 1.7900e-01 + 1.3300e+00 9.0000e-02 -2.0600e-01 + 1.3300e+00 7.9000e-02 -2.2900e-01 + 1.3300e+00 5.8000e-02 -2.3800e-01 + 1.3300e+00 -6.2000e-02 -2.3800e-01 + 1.3300e+00 -8.3000e-02 -2.2900e-01 + 1.3300e+00 -9.4000e-02 -2.0600e-01 + 1.3300e+00 -1.6700e-01 1.7900e-01 + 1.3300e+00 -1.6000e-01 2.0200e-01 + 1.3300e+00 -1.3500e-01 2.1100e-01 + 1.3300e+00 -5.0000e-02 2.1100e-01 + 1.3065e+00 -2.5370e-02 2.4300e-01 + 1.2830e+00 -1.6000e-02 2.6500e-01 + 1.3300e+00 -1.6000e-02 3.5600e-01 + -8.7000e-02 1.2000e+00 -3.5600e-01 + -8.7000e-02 1.2000e+00 -2.6500e-01 + -7.1000e-02 1.2000e+00 -2.4300e-01 + -5.5000e-02 1.2000e+00 -2.1100e-01 + 1.6900e-01 1.2000e+00 -2.1100e-01 + 1.9100e-01 1.1880e+00 -2.0200e-01 + 2.0100e-01 1.1620e+00 -1.7900e-01 + 2.0100e-01 7.9400e-01 2.0600e-01 + 1.9100e-01 7.7500e-01 2.2900e-01 + 1.6900e-01 7.6800e-01 2.3800e-01 + -1.6800e-01 7.6800e-01 2.3800e-01 + -1.9100e-01 7.7500e-01 2.2900e-01 + -2.0000e-01 7.9500e-01 2.0600e-01 + -2.0000e-01 1.1620e+00 -1.7900e-01 + -1.9100e-01 1.1880e+00 -2.0200e-01 + -1.6800e-01 1.2000e+00 -2.1100e-01 + -1.5100e-01 1.2000e+00 -2.1100e-01 + -1.3500e-01 1.2000e+00 -2.4300e-01 + -1.1900e-01 1.2000e+00 -2.6500e-01 + -1.1900e-01 1.2000e+00 -3.5600e-01 + -1.3300e+00 1.6000e-02 3.5600e-01 + -1.2830e+00 1.6000e-02 2.6500e-01 + -1.3065e+00 2.5370e-02 2.4300e-01 + -1.3300e+00 4.8000e-02 2.1100e-01 + -1.3300e+00 6.1000e-02 2.1100e-01 + -1.3300e+00 8.2000e-02 2.0200e-01 + -1.3300e+00 9.3000e-02 1.7900e-01 + -1.3300e+00 1.7100e-01 -2.0600e-01 + -1.3300e+00 1.6500e-01 -2.2900e-01 + -1.3300e+00 1.4100e-01 -2.3800e-01 + -1.3300e+00 -1.4100e-01 -2.3800e-01 + -1.3300e+00 -1.6600e-01 -2.2900e-01 + -1.3300e+00 -1.7200e-01 -2.0600e-01 + -1.3300e+00 -9.3000e-02 1.7900e-01 + -1.3300e+00 -8.2000e-02 2.0200e-01 + -1.3300e+00 -6.2000e-02 2.1100e-01 + -1.3300e+00 -4.9000e-02 2.1100e-01 + -1.3065e+00 -2.5370e-02 2.4300e-01 + -1.2830e+00 -1.6000e-02 2.6500e-01 + -1.3300e+00 -1.6000e-02 3.5600e-01 + 8.7000e-02 -7.7650e-01 -3.5600e-01 + 8.7000e-02 -7.7650e-01 -2.6500e-01 + 7.1000e-02 -7.7650e-01 -2.4300e-01 + 5.5000e-02 -7.7650e-01 -2.1100e-01 + 5.5000e-02 -7.7650e-01 -2.1100e-01 + 3.2600e-02 -7.8350e-01 -2.0200e-01 + 2.2600e-02 -8.0250e-01 -1.7900e-01 + 2.2600e-02 -1.2015e+00 2.0600e-01 + 3.2600e-02 -1.2275e+00 2.2900e-01 + 5.4600e-02 -1.2395e+00 2.3800e-01 + 1.6800e-01 -1.2395e+00 2.3800e-01 + 1.9100e-01 -1.2275e+00 2.2900e-01 + 2.0000e-01 -1.2015e+00 2.0600e-01 + 2.0000e-01 -8.0250e-01 -1.7900e-01 + 1.9100e-01 -7.8350e-01 -2.0200e-01 + 1.6800e-01 -7.7650e-01 -2.1100e-01 + 1.5100e-01 -7.7650e-01 -2.1100e-01 + 1.3500e-01 -7.7650e-01 -2.4300e-01 + 1.1900e-01 -7.7650e-01 -2.6500e-01 + 1.1900e-01 -7.7650e-01 -3.5600e-01 diff --git a/src/ForcingTerms/coil_geometries/jtext_u.dat b/src/ForcingTerms/coil_geometries/jtext_u.dat index 45404b00f..b70ef435f 100644 --- a/src/ForcingTerms/coil_geometries/jtext_u.dat +++ b/src/ForcingTerms/coil_geometries/jtext_u.dat @@ -1,81 +1,81 @@ - 4 1 20 1.00 - 1.2000e+00 1.6000e-02 3.9800e-01 - 1.2000e+00 1.6000e-02 3.3300e-01 - 1.2000e+00 2.5370e-02 3.1000e-01 - 1.2000e+00 4.8000e-02 3.0100e-01 - 1.2000e+00 1.3200e-01 3.0100e-01 - 1.1880e+00 1.5800e-01 3.0100e-01 - 1.1620e+00 1.6300e-01 3.0100e-01 - 7.9400e-01 9.0000e-02 3.0100e-01 - 7.7500e-01 7.9000e-02 3.0100e-01 - 7.6800e-01 5.8000e-02 3.0100e-01 - 7.6800e-01 -6.2000e-02 3.0100e-01 - 7.7500e-01 -8.3000e-02 3.0100e-01 - 7.9500e-01 -9.4000e-02 3.0100e-01 - 1.1620e+00 -1.6700e-01 3.0100e-01 - 1.1880e+00 -1.6000e-01 3.0100e-01 - 1.2000e+00 -1.3500e-01 3.0100e-01 - 1.2000e+00 -5.0000e-02 3.0100e-01 - 1.2000e+00 -2.5370e-02 3.1000e-01 - 1.2000e+00 -1.6000e-02 3.3300e-01 - 1.2000e+00 -1.6000e-02 3.9800e-01 - 1.6000e-02 1.2000e+00 3.9800e-01 - 1.6000e-02 1.2000e+00 3.3300e-01 - 2.5370e-02 1.2000e+00 3.1000e-01 - 4.8000e-02 1.2000e+00 3.0100e-01 - 1.3200e-01 1.2000e+00 3.0100e-01 - 1.5800e-01 1.1880e+00 3.0100e-01 - 1.6300e-01 1.1620e+00 3.0100e-01 - 9.0000e-02 7.9400e-01 3.0100e-01 - 7.9000e-02 7.7500e-01 3.0100e-01 - 5.8000e-02 7.6800e-01 3.0100e-01 - -6.2000e-02 7.6800e-01 3.0100e-01 - -8.3000e-02 7.7500e-01 3.0100e-01 - -9.4000e-02 7.9500e-01 3.0100e-01 - -1.6700e-01 1.1620e+00 3.0100e-01 - -1.6000e-01 1.1880e+00 3.0100e-01 - -1.3500e-01 1.2000e+00 3.0100e-01 - -5.0000e-02 1.2000e+00 3.0100e-01 - -2.5370e-02 1.2000e+00 3.1000e-01 - -1.6000e-02 1.2000e+00 3.3300e-01 - -1.6000e-02 1.2000e+00 3.9800e-01 - -7.7650e-01 1.6000e-02 3.9800e-01 - -7.7650e-01 1.6000e-02 3.3300e-01 - -7.7650e-01 2.5370e-02 3.1000e-01 - -7.7650e-01 4.8000e-02 3.0100e-01 - -7.7650e-01 6.1000e-02 3.0100e-01 - -7.8350e-01 8.2000e-02 3.0100e-01 - -8.0250e-01 9.3000e-02 3.0100e-01 - -1.2015e+00 1.7100e-01 3.0100e-01 - -1.2275e+00 1.6500e-01 3.0100e-01 - -1.2395e+00 1.4100e-01 3.0100e-01 - -1.2395e+00 -1.4100e-01 3.0100e-01 - -1.2275e+00 -1.6600e-01 3.0100e-01 - -1.2015e+00 -1.7200e-01 3.0100e-01 - -8.0250e-01 -9.3000e-02 3.0100e-01 - -7.8350e-01 -8.2000e-02 3.0100e-01 - -7.7650e-01 -6.2000e-02 3.0100e-01 - -7.7650e-01 -4.9000e-02 3.0100e-01 - -7.7650e-01 -2.5370e-02 3.1000e-01 - -7.7650e-01 -1.6000e-02 3.3300e-01 - -7.7650e-01 -1.6000e-02 3.9800e-01 - 1.6000e-02 -7.7650e-01 3.9800e-01 - 1.6000e-02 -7.7650e-01 3.3300e-01 - 2.5370e-02 -7.7650e-01 3.1000e-01 - 4.8000e-02 -7.7650e-01 3.0100e-01 - 6.1000e-02 -7.7650e-01 3.0100e-01 - 8.2000e-02 -7.8350e-01 3.0100e-01 - 9.3000e-02 -8.0250e-01 3.0100e-01 - 1.7100e-01 -1.2015e+00 3.0100e-01 - 1.6500e-01 -1.2275e+00 3.0100e-01 - 1.4100e-01 -1.2395e+00 3.0100e-01 - -1.4100e-01 -1.2395e+00 3.0100e-01 - -1.6600e-01 -1.2275e+00 3.0100e-01 - -1.7200e-01 -1.2015e+00 3.0100e-01 - -9.3000e-02 -8.0250e-01 3.0100e-01 - -8.2000e-02 -7.8350e-01 3.0100e-01 - -6.2000e-02 -7.7650e-01 3.0100e-01 - -4.9000e-02 -7.7650e-01 3.0100e-01 - -2.5370e-02 -7.7650e-01 3.1000e-01 - -1.6000e-02 -7.7650e-01 3.3300e-01 - -1.6000e-02 -7.7650e-01 3.9800e-01 + 4 1 20 1.00 + 1.2000e+00 1.6000e-02 3.9800e-01 + 1.2000e+00 1.6000e-02 3.3300e-01 + 1.2000e+00 2.5370e-02 3.1000e-01 + 1.2000e+00 4.8000e-02 3.0100e-01 + 1.2000e+00 1.3200e-01 3.0100e-01 + 1.1880e+00 1.5800e-01 3.0100e-01 + 1.1620e+00 1.6300e-01 3.0100e-01 + 7.9400e-01 9.0000e-02 3.0100e-01 + 7.7500e-01 7.9000e-02 3.0100e-01 + 7.6800e-01 5.8000e-02 3.0100e-01 + 7.6800e-01 -6.2000e-02 3.0100e-01 + 7.7500e-01 -8.3000e-02 3.0100e-01 + 7.9500e-01 -9.4000e-02 3.0100e-01 + 1.1620e+00 -1.6700e-01 3.0100e-01 + 1.1880e+00 -1.6000e-01 3.0100e-01 + 1.2000e+00 -1.3500e-01 3.0100e-01 + 1.2000e+00 -5.0000e-02 3.0100e-01 + 1.2000e+00 -2.5370e-02 3.1000e-01 + 1.2000e+00 -1.6000e-02 3.3300e-01 + 1.2000e+00 -1.6000e-02 3.9800e-01 + 1.6000e-02 1.2000e+00 3.9800e-01 + 1.6000e-02 1.2000e+00 3.3300e-01 + 2.5370e-02 1.2000e+00 3.1000e-01 + 4.8000e-02 1.2000e+00 3.0100e-01 + 1.3200e-01 1.2000e+00 3.0100e-01 + 1.5800e-01 1.1880e+00 3.0100e-01 + 1.6300e-01 1.1620e+00 3.0100e-01 + 9.0000e-02 7.9400e-01 3.0100e-01 + 7.9000e-02 7.7500e-01 3.0100e-01 + 5.8000e-02 7.6800e-01 3.0100e-01 + -6.2000e-02 7.6800e-01 3.0100e-01 + -8.3000e-02 7.7500e-01 3.0100e-01 + -9.4000e-02 7.9500e-01 3.0100e-01 + -1.6700e-01 1.1620e+00 3.0100e-01 + -1.6000e-01 1.1880e+00 3.0100e-01 + -1.3500e-01 1.2000e+00 3.0100e-01 + -5.0000e-02 1.2000e+00 3.0100e-01 + -2.5370e-02 1.2000e+00 3.1000e-01 + -1.6000e-02 1.2000e+00 3.3300e-01 + -1.6000e-02 1.2000e+00 3.9800e-01 + -7.7650e-01 1.6000e-02 3.9800e-01 + -7.7650e-01 1.6000e-02 3.3300e-01 + -7.7650e-01 2.5370e-02 3.1000e-01 + -7.7650e-01 4.8000e-02 3.0100e-01 + -7.7650e-01 6.1000e-02 3.0100e-01 + -7.8350e-01 8.2000e-02 3.0100e-01 + -8.0250e-01 9.3000e-02 3.0100e-01 + -1.2015e+00 1.7100e-01 3.0100e-01 + -1.2275e+00 1.6500e-01 3.0100e-01 + -1.2395e+00 1.4100e-01 3.0100e-01 + -1.2395e+00 -1.4100e-01 3.0100e-01 + -1.2275e+00 -1.6600e-01 3.0100e-01 + -1.2015e+00 -1.7200e-01 3.0100e-01 + -8.0250e-01 -9.3000e-02 3.0100e-01 + -7.8350e-01 -8.2000e-02 3.0100e-01 + -7.7650e-01 -6.2000e-02 3.0100e-01 + -7.7650e-01 -4.9000e-02 3.0100e-01 + -7.7650e-01 -2.5370e-02 3.1000e-01 + -7.7650e-01 -1.6000e-02 3.3300e-01 + -7.7650e-01 -1.6000e-02 3.9800e-01 + 1.6000e-02 -7.7650e-01 3.9800e-01 + 1.6000e-02 -7.7650e-01 3.3300e-01 + 2.5370e-02 -7.7650e-01 3.1000e-01 + 4.8000e-02 -7.7650e-01 3.0100e-01 + 6.1000e-02 -7.7650e-01 3.0100e-01 + 8.2000e-02 -7.8350e-01 3.0100e-01 + 9.3000e-02 -8.0250e-01 3.0100e-01 + 1.7100e-01 -1.2015e+00 3.0100e-01 + 1.6500e-01 -1.2275e+00 3.0100e-01 + 1.4100e-01 -1.2395e+00 3.0100e-01 + -1.4100e-01 -1.2395e+00 3.0100e-01 + -1.6600e-01 -1.2275e+00 3.0100e-01 + -1.7200e-01 -1.2015e+00 3.0100e-01 + -9.3000e-02 -8.0250e-01 3.0100e-01 + -8.2000e-02 -7.8350e-01 3.0100e-01 + -6.2000e-02 -7.7650e-01 3.0100e-01 + -4.9000e-02 -7.7650e-01 3.0100e-01 + -2.5370e-02 -7.7650e-01 3.1000e-01 + -1.6000e-02 -7.7650e-01 3.3300e-01 + -1.6000e-02 -7.7650e-01 3.9800e-01 diff --git a/src/ForcingTerms/coil_geometries/mastu_efcc.dat b/src/ForcingTerms/coil_geometries/mastu_efcc.dat index e94da889f..5259e11cc 100644 --- a/src/ForcingTerms/coil_geometries/mastu_efcc.dat +++ b/src/ForcingTerms/coil_geometries/mastu_efcc.dat @@ -1,169 +1,169 @@ - 4 1 42 1.00 - 2.9319e+00 0.0000e+00 1.6550e+00 - 2.9213e+00 2.4953e-01 1.6550e+00 - 2.8894e+00 4.9726e-01 1.6550e+00 - 2.8366e+00 7.4137e-01 1.6550e+00 - 2.7632e+00 9.8011e-01 1.6550e+00 - 2.6698e+00 1.2117e+00 1.6550e+00 - 2.5570e+00 1.4346e+00 1.6550e+00 - 2.4256e+00 1.6470e+00 1.6550e+00 - 2.2766e+00 1.8474e+00 1.6550e+00 - 2.1111e+00 2.0345e+00 1.6550e+00 - 1.9303e+00 2.2068e+00 1.6550e+00 - 1.7355e+00 2.3631e+00 1.6550e+00 - 1.5281e+00 2.5022e+00 1.6550e+00 - 1.3096e+00 2.6232e+00 1.6550e+00 - 1.0815e+00 2.7251e+00 1.6550e+00 - 8.4568e-01 2.8073e+00 1.6550e+00 - 6.0369e-01 2.8691e+00 1.6550e+00 - 3.5731e-01 2.9100e+00 1.6550e+00 - 3.5731e-01 2.9100e+00 1.6550e+00 - 3.5729e-01 2.9099e+00 9.1800e-01 - 3.5727e-01 2.9097e+00 1.8100e-01 - 3.5725e-01 2.9096e+00 -5.5600e-01 - 3.5723e-01 2.9094e+00 -1.2930e+00 - 3.5721e-01 2.9093e+00 -2.0300e+00 - 6.7851e-01 2.8515e+00 -2.0300e+00 - 9.9139e-01 2.7583e+00 -2.0300e+00 - 1.2920e+00 2.6310e+00 -2.0300e+00 - 1.5765e+00 2.4710e+00 -2.0300e+00 - 1.8415e+00 2.2804e+00 -2.0300e+00 - 2.0837e+00 2.0614e+00 -2.0300e+00 - 2.3000e+00 1.8169e+00 -2.0300e+00 - 2.4878e+00 1.5499e+00 -2.0300e+00 - 2.6447e+00 1.2636e+00 -2.0300e+00 - 2.7688e+00 9.6171e-01 -2.0300e+00 - 2.8586e+00 6.4785e-01 -2.0300e+00 - 2.9129e+00 3.2594e-01 -2.0300e+00 - 2.9311e+00 0.0000e+00 -2.0300e+00 - 2.9313e+00 0.0000e+00 -1.2930e+00 - 2.9314e+00 0.0000e+00 -5.5600e-01 - 2.9316e+00 0.0000e+00 1.8100e-01 - 2.9317e+00 0.0000e+00 9.1800e-01 - 2.9319e+00 0.0000e+00 1.6550e+00 - 1.7953e-16 2.9319e+00 1.6550e+00 - -2.4953e-01 2.9213e+00 1.6550e+00 - -4.9726e-01 2.8894e+00 1.6550e+00 - -7.4137e-01 2.8366e+00 1.6550e+00 - -9.8011e-01 2.7632e+00 1.6550e+00 - -1.2117e+00 2.6698e+00 1.6550e+00 - -1.4346e+00 2.5570e+00 1.6550e+00 - -1.6470e+00 2.4256e+00 1.6550e+00 - -1.8474e+00 2.2766e+00 1.6550e+00 - -2.0345e+00 2.1111e+00 1.6550e+00 - -2.2068e+00 1.9303e+00 1.6550e+00 - -2.3631e+00 1.7355e+00 1.6550e+00 - -2.5022e+00 1.5281e+00 1.6550e+00 - -2.6232e+00 1.3096e+00 1.6550e+00 - -2.7251e+00 1.0815e+00 1.6550e+00 - -2.8073e+00 8.4568e-01 1.6550e+00 - -2.8691e+00 6.0369e-01 1.6550e+00 - -2.9100e+00 3.5731e-01 1.6550e+00 - -2.9100e+00 3.5731e-01 1.6550e+00 - -2.9099e+00 3.5729e-01 9.1800e-01 - -2.9097e+00 3.5727e-01 1.8100e-01 - -2.9096e+00 3.5725e-01 -5.5600e-01 - -2.9094e+00 3.5723e-01 -1.2930e+00 - -2.9093e+00 3.5721e-01 -2.0300e+00 - -2.8515e+00 6.7851e-01 -2.0300e+00 - -2.7583e+00 9.9139e-01 -2.0300e+00 - -2.6310e+00 1.2920e+00 -2.0300e+00 - -2.4710e+00 1.5765e+00 -2.0300e+00 - -2.2804e+00 1.8415e+00 -2.0300e+00 - -2.0614e+00 2.0837e+00 -2.0300e+00 - -1.8169e+00 2.3000e+00 -2.0300e+00 - -1.5499e+00 2.4878e+00 -2.0300e+00 - -1.2636e+00 2.6447e+00 -2.0300e+00 - -9.6171e-01 2.7688e+00 -2.0300e+00 - -6.4785e-01 2.8586e+00 -2.0300e+00 - -3.2594e-01 2.9129e+00 -2.0300e+00 - 1.7948e-16 2.9311e+00 -2.0300e+00 - 1.7949e-16 2.9313e+00 -1.2930e+00 - 1.7950e-16 2.9314e+00 -5.5600e-01 - 1.7951e-16 2.9316e+00 1.8100e-01 - 1.7952e-16 2.9317e+00 9.1800e-01 - 1.7953e-16 2.9319e+00 1.6550e+00 - -2.9319e+00 3.5905e-16 1.6550e+00 - -2.9213e+00 -2.4953e-01 1.6550e+00 - -2.8894e+00 -4.9726e-01 1.6550e+00 - -2.8366e+00 -7.4137e-01 1.6550e+00 - -2.7632e+00 -9.8011e-01 1.6550e+00 - -2.6698e+00 -1.2117e+00 1.6550e+00 - -2.5570e+00 -1.4346e+00 1.6550e+00 - -2.4256e+00 -1.6470e+00 1.6550e+00 - -2.2766e+00 -1.8474e+00 1.6550e+00 - -2.1111e+00 -2.0345e+00 1.6550e+00 - -1.9303e+00 -2.2068e+00 1.6550e+00 - -1.7355e+00 -2.3631e+00 1.6550e+00 - -1.5281e+00 -2.5022e+00 1.6550e+00 - -1.3096e+00 -2.6232e+00 1.6550e+00 - -1.0815e+00 -2.7251e+00 1.6550e+00 - -8.4568e-01 -2.8073e+00 1.6550e+00 - -6.0369e-01 -2.8691e+00 1.6550e+00 - -3.5731e-01 -2.9100e+00 1.6550e+00 - -3.5731e-01 -2.9100e+00 1.6550e+00 - -3.5729e-01 -2.9099e+00 9.1800e-01 - -3.5727e-01 -2.9097e+00 1.8100e-01 - -3.5725e-01 -2.9096e+00 -5.5600e-01 - -3.5723e-01 -2.9094e+00 -1.2930e+00 - -3.5721e-01 -2.9093e+00 -2.0300e+00 - -6.7851e-01 -2.8515e+00 -2.0300e+00 - -9.9139e-01 -2.7583e+00 -2.0300e+00 - -1.2920e+00 -2.6310e+00 -2.0300e+00 - -1.5765e+00 -2.4710e+00 -2.0300e+00 - -1.8415e+00 -2.2804e+00 -2.0300e+00 - -2.0837e+00 -2.0614e+00 -2.0300e+00 - -2.3000e+00 -1.8169e+00 -2.0300e+00 - -2.4878e+00 -1.5499e+00 -2.0300e+00 - -2.6447e+00 -1.2636e+00 -2.0300e+00 - -2.7688e+00 -9.6171e-01 -2.0300e+00 - -2.8586e+00 -6.4785e-01 -2.0300e+00 - -2.9129e+00 -3.2594e-01 -2.0300e+00 - -2.9311e+00 3.5896e-16 -2.0300e+00 - -2.9313e+00 3.5898e-16 -1.2930e+00 - -2.9314e+00 3.5900e-16 -5.5600e-01 - -2.9316e+00 3.5902e-16 1.8100e-01 - -2.9317e+00 3.5903e-16 9.1800e-01 - -2.9319e+00 3.5905e-16 1.6550e+00 - -5.3858e-16 -2.9319e+00 1.6550e+00 - 2.4953e-01 -2.9213e+00 1.6550e+00 - 4.9726e-01 -2.8894e+00 1.6550e+00 - 7.4137e-01 -2.8366e+00 1.6550e+00 - 9.8011e-01 -2.7632e+00 1.6550e+00 - 1.2117e+00 -2.6698e+00 1.6550e+00 - 1.4346e+00 -2.5570e+00 1.6550e+00 - 1.6470e+00 -2.4256e+00 1.6550e+00 - 1.8474e+00 -2.2766e+00 1.6550e+00 - 2.0345e+00 -2.1111e+00 1.6550e+00 - 2.2068e+00 -1.9303e+00 1.6550e+00 - 2.3631e+00 -1.7355e+00 1.6550e+00 - 2.5022e+00 -1.5281e+00 1.6550e+00 - 2.6232e+00 -1.3096e+00 1.6550e+00 - 2.7251e+00 -1.0815e+00 1.6550e+00 - 2.8073e+00 -8.4568e-01 1.6550e+00 - 2.8691e+00 -6.0369e-01 1.6550e+00 - 2.9100e+00 -3.5731e-01 1.6550e+00 - 2.9100e+00 -3.5731e-01 1.6550e+00 - 2.9099e+00 -3.5729e-01 9.1800e-01 - 2.9097e+00 -3.5727e-01 1.8100e-01 - 2.9096e+00 -3.5725e-01 -5.5600e-01 - 2.9094e+00 -3.5723e-01 -1.2930e+00 - 2.9093e+00 -3.5721e-01 -2.0300e+00 - 2.8515e+00 -6.7851e-01 -2.0300e+00 - 2.7583e+00 -9.9139e-01 -2.0300e+00 - 2.6310e+00 -1.2920e+00 -2.0300e+00 - 2.4710e+00 -1.5765e+00 -2.0300e+00 - 2.2804e+00 -1.8415e+00 -2.0300e+00 - 2.0614e+00 -2.0837e+00 -2.0300e+00 - 1.8169e+00 -2.3000e+00 -2.0300e+00 - 1.5499e+00 -2.4878e+00 -2.0300e+00 - 1.2636e+00 -2.6447e+00 -2.0300e+00 - 9.6171e-01 -2.7688e+00 -2.0300e+00 - 6.4785e-01 -2.8586e+00 -2.0300e+00 - 3.2594e-01 -2.9129e+00 -2.0300e+00 - -5.3843e-16 -2.9311e+00 -2.0300e+00 - -5.3846e-16 -2.9313e+00 -1.2930e+00 - -5.3849e-16 -2.9314e+00 -5.5600e-01 - -5.3852e-16 -2.9316e+00 1.8100e-01 - -5.3855e-16 -2.9317e+00 9.1800e-01 - -5.3858e-16 -2.9319e+00 1.6550e+00 + 4 1 42 1.00 + 2.9319e+00 0.0000e+00 1.6550e+00 + 2.9213e+00 2.4953e-01 1.6550e+00 + 2.8894e+00 4.9726e-01 1.6550e+00 + 2.8366e+00 7.4137e-01 1.6550e+00 + 2.7632e+00 9.8011e-01 1.6550e+00 + 2.6698e+00 1.2117e+00 1.6550e+00 + 2.5570e+00 1.4346e+00 1.6550e+00 + 2.4256e+00 1.6470e+00 1.6550e+00 + 2.2766e+00 1.8474e+00 1.6550e+00 + 2.1111e+00 2.0345e+00 1.6550e+00 + 1.9303e+00 2.2068e+00 1.6550e+00 + 1.7355e+00 2.3631e+00 1.6550e+00 + 1.5281e+00 2.5022e+00 1.6550e+00 + 1.3096e+00 2.6232e+00 1.6550e+00 + 1.0815e+00 2.7251e+00 1.6550e+00 + 8.4568e-01 2.8073e+00 1.6550e+00 + 6.0369e-01 2.8691e+00 1.6550e+00 + 3.5731e-01 2.9100e+00 1.6550e+00 + 3.5731e-01 2.9100e+00 1.6550e+00 + 3.5729e-01 2.9099e+00 9.1800e-01 + 3.5727e-01 2.9097e+00 1.8100e-01 + 3.5725e-01 2.9096e+00 -5.5600e-01 + 3.5723e-01 2.9094e+00 -1.2930e+00 + 3.5721e-01 2.9093e+00 -2.0300e+00 + 6.7851e-01 2.8515e+00 -2.0300e+00 + 9.9139e-01 2.7583e+00 -2.0300e+00 + 1.2920e+00 2.6310e+00 -2.0300e+00 + 1.5765e+00 2.4710e+00 -2.0300e+00 + 1.8415e+00 2.2804e+00 -2.0300e+00 + 2.0837e+00 2.0614e+00 -2.0300e+00 + 2.3000e+00 1.8169e+00 -2.0300e+00 + 2.4878e+00 1.5499e+00 -2.0300e+00 + 2.6447e+00 1.2636e+00 -2.0300e+00 + 2.7688e+00 9.6171e-01 -2.0300e+00 + 2.8586e+00 6.4785e-01 -2.0300e+00 + 2.9129e+00 3.2594e-01 -2.0300e+00 + 2.9311e+00 0.0000e+00 -2.0300e+00 + 2.9313e+00 0.0000e+00 -1.2930e+00 + 2.9314e+00 0.0000e+00 -5.5600e-01 + 2.9316e+00 0.0000e+00 1.8100e-01 + 2.9317e+00 0.0000e+00 9.1800e-01 + 2.9319e+00 0.0000e+00 1.6550e+00 + 1.7953e-16 2.9319e+00 1.6550e+00 + -2.4953e-01 2.9213e+00 1.6550e+00 + -4.9726e-01 2.8894e+00 1.6550e+00 + -7.4137e-01 2.8366e+00 1.6550e+00 + -9.8011e-01 2.7632e+00 1.6550e+00 + -1.2117e+00 2.6698e+00 1.6550e+00 + -1.4346e+00 2.5570e+00 1.6550e+00 + -1.6470e+00 2.4256e+00 1.6550e+00 + -1.8474e+00 2.2766e+00 1.6550e+00 + -2.0345e+00 2.1111e+00 1.6550e+00 + -2.2068e+00 1.9303e+00 1.6550e+00 + -2.3631e+00 1.7355e+00 1.6550e+00 + -2.5022e+00 1.5281e+00 1.6550e+00 + -2.6232e+00 1.3096e+00 1.6550e+00 + -2.7251e+00 1.0815e+00 1.6550e+00 + -2.8073e+00 8.4568e-01 1.6550e+00 + -2.8691e+00 6.0369e-01 1.6550e+00 + -2.9100e+00 3.5731e-01 1.6550e+00 + -2.9100e+00 3.5731e-01 1.6550e+00 + -2.9099e+00 3.5729e-01 9.1800e-01 + -2.9097e+00 3.5727e-01 1.8100e-01 + -2.9096e+00 3.5725e-01 -5.5600e-01 + -2.9094e+00 3.5723e-01 -1.2930e+00 + -2.9093e+00 3.5721e-01 -2.0300e+00 + -2.8515e+00 6.7851e-01 -2.0300e+00 + -2.7583e+00 9.9139e-01 -2.0300e+00 + -2.6310e+00 1.2920e+00 -2.0300e+00 + -2.4710e+00 1.5765e+00 -2.0300e+00 + -2.2804e+00 1.8415e+00 -2.0300e+00 + -2.0614e+00 2.0837e+00 -2.0300e+00 + -1.8169e+00 2.3000e+00 -2.0300e+00 + -1.5499e+00 2.4878e+00 -2.0300e+00 + -1.2636e+00 2.6447e+00 -2.0300e+00 + -9.6171e-01 2.7688e+00 -2.0300e+00 + -6.4785e-01 2.8586e+00 -2.0300e+00 + -3.2594e-01 2.9129e+00 -2.0300e+00 + 1.7948e-16 2.9311e+00 -2.0300e+00 + 1.7949e-16 2.9313e+00 -1.2930e+00 + 1.7950e-16 2.9314e+00 -5.5600e-01 + 1.7951e-16 2.9316e+00 1.8100e-01 + 1.7952e-16 2.9317e+00 9.1800e-01 + 1.7953e-16 2.9319e+00 1.6550e+00 + -2.9319e+00 3.5905e-16 1.6550e+00 + -2.9213e+00 -2.4953e-01 1.6550e+00 + -2.8894e+00 -4.9726e-01 1.6550e+00 + -2.8366e+00 -7.4137e-01 1.6550e+00 + -2.7632e+00 -9.8011e-01 1.6550e+00 + -2.6698e+00 -1.2117e+00 1.6550e+00 + -2.5570e+00 -1.4346e+00 1.6550e+00 + -2.4256e+00 -1.6470e+00 1.6550e+00 + -2.2766e+00 -1.8474e+00 1.6550e+00 + -2.1111e+00 -2.0345e+00 1.6550e+00 + -1.9303e+00 -2.2068e+00 1.6550e+00 + -1.7355e+00 -2.3631e+00 1.6550e+00 + -1.5281e+00 -2.5022e+00 1.6550e+00 + -1.3096e+00 -2.6232e+00 1.6550e+00 + -1.0815e+00 -2.7251e+00 1.6550e+00 + -8.4568e-01 -2.8073e+00 1.6550e+00 + -6.0369e-01 -2.8691e+00 1.6550e+00 + -3.5731e-01 -2.9100e+00 1.6550e+00 + -3.5731e-01 -2.9100e+00 1.6550e+00 + -3.5729e-01 -2.9099e+00 9.1800e-01 + -3.5727e-01 -2.9097e+00 1.8100e-01 + -3.5725e-01 -2.9096e+00 -5.5600e-01 + -3.5723e-01 -2.9094e+00 -1.2930e+00 + -3.5721e-01 -2.9093e+00 -2.0300e+00 + -6.7851e-01 -2.8515e+00 -2.0300e+00 + -9.9139e-01 -2.7583e+00 -2.0300e+00 + -1.2920e+00 -2.6310e+00 -2.0300e+00 + -1.5765e+00 -2.4710e+00 -2.0300e+00 + -1.8415e+00 -2.2804e+00 -2.0300e+00 + -2.0837e+00 -2.0614e+00 -2.0300e+00 + -2.3000e+00 -1.8169e+00 -2.0300e+00 + -2.4878e+00 -1.5499e+00 -2.0300e+00 + -2.6447e+00 -1.2636e+00 -2.0300e+00 + -2.7688e+00 -9.6171e-01 -2.0300e+00 + -2.8586e+00 -6.4785e-01 -2.0300e+00 + -2.9129e+00 -3.2594e-01 -2.0300e+00 + -2.9311e+00 3.5896e-16 -2.0300e+00 + -2.9313e+00 3.5898e-16 -1.2930e+00 + -2.9314e+00 3.5900e-16 -5.5600e-01 + -2.9316e+00 3.5902e-16 1.8100e-01 + -2.9317e+00 3.5903e-16 9.1800e-01 + -2.9319e+00 3.5905e-16 1.6550e+00 + -5.3858e-16 -2.9319e+00 1.6550e+00 + 2.4953e-01 -2.9213e+00 1.6550e+00 + 4.9726e-01 -2.8894e+00 1.6550e+00 + 7.4137e-01 -2.8366e+00 1.6550e+00 + 9.8011e-01 -2.7632e+00 1.6550e+00 + 1.2117e+00 -2.6698e+00 1.6550e+00 + 1.4346e+00 -2.5570e+00 1.6550e+00 + 1.6470e+00 -2.4256e+00 1.6550e+00 + 1.8474e+00 -2.2766e+00 1.6550e+00 + 2.0345e+00 -2.1111e+00 1.6550e+00 + 2.2068e+00 -1.9303e+00 1.6550e+00 + 2.3631e+00 -1.7355e+00 1.6550e+00 + 2.5022e+00 -1.5281e+00 1.6550e+00 + 2.6232e+00 -1.3096e+00 1.6550e+00 + 2.7251e+00 -1.0815e+00 1.6550e+00 + 2.8073e+00 -8.4568e-01 1.6550e+00 + 2.8691e+00 -6.0369e-01 1.6550e+00 + 2.9100e+00 -3.5731e-01 1.6550e+00 + 2.9100e+00 -3.5731e-01 1.6550e+00 + 2.9099e+00 -3.5729e-01 9.1800e-01 + 2.9097e+00 -3.5727e-01 1.8100e-01 + 2.9096e+00 -3.5725e-01 -5.5600e-01 + 2.9094e+00 -3.5723e-01 -1.2930e+00 + 2.9093e+00 -3.5721e-01 -2.0300e+00 + 2.8515e+00 -6.7851e-01 -2.0300e+00 + 2.7583e+00 -9.9139e-01 -2.0300e+00 + 2.6310e+00 -1.2920e+00 -2.0300e+00 + 2.4710e+00 -1.5765e+00 -2.0300e+00 + 2.2804e+00 -1.8415e+00 -2.0300e+00 + 2.0614e+00 -2.0837e+00 -2.0300e+00 + 1.8169e+00 -2.3000e+00 -2.0300e+00 + 1.5499e+00 -2.4878e+00 -2.0300e+00 + 1.2636e+00 -2.6447e+00 -2.0300e+00 + 9.6171e-01 -2.7688e+00 -2.0300e+00 + 6.4785e-01 -2.8586e+00 -2.0300e+00 + 3.2594e-01 -2.9129e+00 -2.0300e+00 + -5.3843e-16 -2.9311e+00 -2.0300e+00 + -5.3846e-16 -2.9313e+00 -1.2930e+00 + -5.3849e-16 -2.9314e+00 -5.5600e-01 + -5.3852e-16 -2.9316e+00 1.8100e-01 + -5.3855e-16 -2.9317e+00 9.1800e-01 + -5.3858e-16 -2.9319e+00 1.6550e+00 diff --git a/src/ForcingTerms/coil_geometries/mastu_rmpl.dat b/src/ForcingTerms/coil_geometries/mastu_rmpl.dat index 7d3a798d3..1bb9ca785 100644 --- a/src/ForcingTerms/coil_geometries/mastu_rmpl.dat +++ b/src/ForcingTerms/coil_geometries/mastu_rmpl.dat @@ -1,337 +1,337 @@ - 8 1 42 1.00 - 1.3110e+00 0.0000e+00 -7.9100e-01 - 1.3107e+00 2.6300e-02 -7.9100e-01 - 1.3099e+00 5.2589e-02 -7.9100e-01 - 1.3086e+00 7.8857e-02 -7.9100e-01 - 1.3068e+00 1.0509e-01 -7.9100e-01 - 1.3044e+00 1.3129e-01 -7.9100e-01 - 1.3015e+00 1.5743e-01 -7.9100e-01 - 1.2981e+00 1.8351e-01 -7.9100e-01 - 1.2942e+00 2.0951e-01 -7.9100e-01 - 1.2897e+00 2.3543e-01 -7.9100e-01 - 1.2847e+00 2.6125e-01 -7.9100e-01 - 1.2792e+00 2.8697e-01 -7.9100e-01 - 1.2732e+00 3.1258e-01 -7.9100e-01 - 1.2667e+00 3.3806e-01 -7.9100e-01 - 1.2596e+00 3.6340e-01 -7.9100e-01 - 1.2521e+00 3.8859e-01 -7.9100e-01 - 1.2440e+00 4.1363e-01 -7.9100e-01 - 1.2355e+00 4.3851e-01 -7.9100e-01 - 1.2264e+00 4.6320e-01 -7.9100e-01 - 1.2169e+00 4.8771e-01 -7.9100e-01 - 1.2169e+00 4.8771e-01 -7.9100e-01 - 1.2703e+00 5.0910e-01 -6.9100e-01 - 1.3237e+00 5.3049e-01 -5.9100e-01 - 1.3352e+00 5.0068e-01 -5.9100e-01 - 1.3461e+00 4.7062e-01 -5.9100e-01 - 1.3563e+00 4.4032e-01 -5.9100e-01 - 1.3658e+00 4.0980e-01 -5.9100e-01 - 1.3747e+00 3.7908e-01 -5.9100e-01 - 1.3828e+00 3.4816e-01 -5.9100e-01 - 1.3903e+00 3.1707e-01 -5.9100e-01 - 1.3971e+00 2.8582e-01 -5.9100e-01 - 1.4031e+00 2.5442e-01 -5.9100e-01 - 1.4085e+00 2.2290e-01 -5.9100e-01 - 1.4131e+00 1.9127e-01 -5.9100e-01 - 1.4170e+00 1.5954e-01 -5.9100e-01 - 1.4203e+00 1.2773e-01 -5.9100e-01 - 1.4228e+00 9.5850e-02 -5.9100e-01 - 1.4246e+00 6.3927e-02 -5.9100e-01 - 1.4256e+00 3.1972e-02 -5.9100e-01 - 1.4260e+00 0.0000e+00 -5.9100e-01 - 1.3685e+00 0.0000e+00 -6.9100e-01 - 1.3110e+00 0.0000e+00 -7.9100e-01 - 9.2702e-01 9.2702e-01 -7.9100e-01 - 9.0823e-01 9.4543e-01 -7.9100e-01 - 8.8909e-01 9.6346e-01 -7.9100e-01 - 8.6958e-01 9.8110e-01 -7.9100e-01 - 8.4972e-01 9.9835e-01 -7.9100e-01 - 8.2952e-01 1.0152e+00 -7.9100e-01 - 8.0899e-01 1.0316e+00 -7.9100e-01 - 7.8813e-01 1.0476e+00 -7.9100e-01 - 7.6696e-01 1.0632e+00 -7.9100e-01 - 7.4547e-01 1.0784e+00 -7.9100e-01 - 7.2369e-01 1.0932e+00 -7.9100e-01 - 7.0161e-01 1.1075e+00 -7.9100e-01 - 6.7926e-01 1.1213e+00 -7.9100e-01 - 6.5663e-01 1.1347e+00 -7.9100e-01 - 6.3373e-01 1.1477e+00 -7.9100e-01 - 6.1058e-01 1.1601e+00 -7.9100e-01 - 5.8718e-01 1.1721e+00 -7.9100e-01 - 5.6355e-01 1.1837e+00 -7.9100e-01 - 5.3969e-01 1.1948e+00 -7.9100e-01 - 5.1562e-01 1.2053e+00 -7.9100e-01 - 5.1562e-01 1.2053e+00 -7.9100e-01 - 5.3823e-01 1.2582e+00 -6.9100e-01 - 5.6085e-01 1.3111e+00 -5.9100e-01 - 5.9010e-01 1.2982e+00 -5.9100e-01 - 6.1906e-01 1.2846e+00 -5.9100e-01 - 6.4770e-01 1.2704e+00 -5.9100e-01 - 6.7602e-01 1.2556e+00 -5.9100e-01 - 7.0400e-01 1.2401e+00 -5.9100e-01 - 7.3163e-01 1.2240e+00 -5.9100e-01 - 7.5889e-01 1.2073e+00 -5.9100e-01 - 7.8577e-01 1.1900e+00 -5.9100e-01 - 8.1225e-01 1.1721e+00 -5.9100e-01 - 8.3832e-01 1.1536e+00 -5.9100e-01 - 8.6398e-01 1.1345e+00 -5.9100e-01 - 8.8919e-01 1.1148e+00 -5.9100e-01 - 9.1397e-01 1.0946e+00 -5.9100e-01 - 9.3828e-01 1.0738e+00 -5.9100e-01 - 9.6212e-01 1.0525e+00 -5.9100e-01 - 9.8547e-01 1.0307e+00 -5.9100e-01 - 1.0083e+00 1.0083e+00 -5.9100e-01 - 9.6768e-01 9.6768e-01 -6.9100e-01 - 9.2702e-01 9.2702e-01 -7.9100e-01 - 8.0276e-17 1.3110e+00 -7.9100e-01 - -2.6300e-02 1.3107e+00 -7.9100e-01 - -5.2589e-02 1.3099e+00 -7.9100e-01 - -7.8857e-02 1.3086e+00 -7.9100e-01 - -1.0509e-01 1.3068e+00 -7.9100e-01 - -1.3129e-01 1.3044e+00 -7.9100e-01 - -1.5743e-01 1.3015e+00 -7.9100e-01 - -1.8351e-01 1.2981e+00 -7.9100e-01 - -2.0951e-01 1.2942e+00 -7.9100e-01 - -2.3543e-01 1.2897e+00 -7.9100e-01 - -2.6125e-01 1.2847e+00 -7.9100e-01 - -2.8697e-01 1.2792e+00 -7.9100e-01 - -3.1258e-01 1.2732e+00 -7.9100e-01 - -3.3806e-01 1.2667e+00 -7.9100e-01 - -3.6340e-01 1.2596e+00 -7.9100e-01 - -3.8859e-01 1.2521e+00 -7.9100e-01 - -4.1363e-01 1.2440e+00 -7.9100e-01 - -4.3851e-01 1.2355e+00 -7.9100e-01 - -4.6320e-01 1.2264e+00 -7.9100e-01 - -4.8771e-01 1.2169e+00 -7.9100e-01 - -4.8771e-01 1.2169e+00 -7.9100e-01 - -5.0910e-01 1.2703e+00 -6.9100e-01 - -5.3049e-01 1.3237e+00 -5.9100e-01 - -5.0068e-01 1.3352e+00 -5.9100e-01 - -4.7062e-01 1.3461e+00 -5.9100e-01 - -4.4032e-01 1.3563e+00 -5.9100e-01 - -4.0980e-01 1.3658e+00 -5.9100e-01 - -3.7908e-01 1.3747e+00 -5.9100e-01 - -3.4816e-01 1.3828e+00 -5.9100e-01 - -3.1707e-01 1.3903e+00 -5.9100e-01 - -2.8582e-01 1.3971e+00 -5.9100e-01 - -2.5442e-01 1.4031e+00 -5.9100e-01 - -2.2290e-01 1.4085e+00 -5.9100e-01 - -1.9127e-01 1.4131e+00 -5.9100e-01 - -1.5954e-01 1.4170e+00 -5.9100e-01 - -1.2773e-01 1.4203e+00 -5.9100e-01 - -9.5850e-02 1.4228e+00 -5.9100e-01 - -6.3927e-02 1.4246e+00 -5.9100e-01 - -3.1972e-02 1.4256e+00 -5.9100e-01 - 8.7317e-17 1.4260e+00 -5.9100e-01 - 8.3796e-17 1.3685e+00 -6.9100e-01 - 8.0276e-17 1.3110e+00 -7.9100e-01 - -9.2702e-01 9.2702e-01 -7.9100e-01 - -9.4543e-01 9.0823e-01 -7.9100e-01 - -9.6346e-01 8.8909e-01 -7.9100e-01 - -9.8110e-01 8.6958e-01 -7.9100e-01 - -9.9835e-01 8.4972e-01 -7.9100e-01 - -1.0152e+00 8.2952e-01 -7.9100e-01 - -1.0316e+00 8.0899e-01 -7.9100e-01 - -1.0476e+00 7.8813e-01 -7.9100e-01 - -1.0632e+00 7.6696e-01 -7.9100e-01 - -1.0784e+00 7.4547e-01 -7.9100e-01 - -1.0932e+00 7.2369e-01 -7.9100e-01 - -1.1075e+00 7.0161e-01 -7.9100e-01 - -1.1213e+00 6.7926e-01 -7.9100e-01 - -1.1347e+00 6.5663e-01 -7.9100e-01 - -1.1477e+00 6.3373e-01 -7.9100e-01 - -1.1601e+00 6.1058e-01 -7.9100e-01 - -1.1721e+00 5.8718e-01 -7.9100e-01 - -1.1837e+00 5.6355e-01 -7.9100e-01 - -1.1948e+00 5.3969e-01 -7.9100e-01 - -1.2053e+00 5.1562e-01 -7.9100e-01 - -1.2053e+00 5.1562e-01 -7.9100e-01 - -1.2582e+00 5.3823e-01 -6.9100e-01 - -1.3111e+00 5.6085e-01 -5.9100e-01 - -1.2982e+00 5.9010e-01 -5.9100e-01 - -1.2846e+00 6.1906e-01 -5.9100e-01 - -1.2704e+00 6.4770e-01 -5.9100e-01 - -1.2556e+00 6.7602e-01 -5.9100e-01 - -1.2401e+00 7.0400e-01 -5.9100e-01 - -1.2240e+00 7.3163e-01 -5.9100e-01 - -1.2073e+00 7.5889e-01 -5.9100e-01 - -1.1900e+00 7.8577e-01 -5.9100e-01 - -1.1721e+00 8.1225e-01 -5.9100e-01 - -1.1536e+00 8.3832e-01 -5.9100e-01 - -1.1345e+00 8.6398e-01 -5.9100e-01 - -1.1148e+00 8.8919e-01 -5.9100e-01 - -1.0946e+00 9.1397e-01 -5.9100e-01 - -1.0738e+00 9.3828e-01 -5.9100e-01 - -1.0525e+00 9.6212e-01 -5.9100e-01 - -1.0307e+00 9.8547e-01 -5.9100e-01 - -1.0083e+00 1.0083e+00 -5.9100e-01 - -9.6768e-01 9.6768e-01 -6.9100e-01 - -9.2702e-01 9.2702e-01 -7.9100e-01 - -1.3110e+00 1.6055e-16 -7.9100e-01 - -1.3107e+00 -2.6300e-02 -7.9100e-01 - -1.3099e+00 -5.2589e-02 -7.9100e-01 - -1.3086e+00 -7.8857e-02 -7.9100e-01 - -1.3068e+00 -1.0509e-01 -7.9100e-01 - -1.3044e+00 -1.3129e-01 -7.9100e-01 - -1.3015e+00 -1.5743e-01 -7.9100e-01 - -1.2981e+00 -1.8351e-01 -7.9100e-01 - -1.2942e+00 -2.0951e-01 -7.9100e-01 - -1.2897e+00 -2.3543e-01 -7.9100e-01 - -1.2847e+00 -2.6125e-01 -7.9100e-01 - -1.2792e+00 -2.8697e-01 -7.9100e-01 - -1.2732e+00 -3.1258e-01 -7.9100e-01 - -1.2667e+00 -3.3806e-01 -7.9100e-01 - -1.2596e+00 -3.6340e-01 -7.9100e-01 - -1.2521e+00 -3.8859e-01 -7.9100e-01 - -1.2440e+00 -4.1363e-01 -7.9100e-01 - -1.2355e+00 -4.3851e-01 -7.9100e-01 - -1.2264e+00 -4.6320e-01 -7.9100e-01 - -1.2169e+00 -4.8771e-01 -7.9100e-01 - -1.2169e+00 -4.8771e-01 -7.9100e-01 - -1.2703e+00 -5.0910e-01 -6.9100e-01 - -1.3237e+00 -5.3049e-01 -5.9100e-01 - -1.3352e+00 -5.0068e-01 -5.9100e-01 - -1.3461e+00 -4.7062e-01 -5.9100e-01 - -1.3563e+00 -4.4032e-01 -5.9100e-01 - -1.3658e+00 -4.0980e-01 -5.9100e-01 - -1.3747e+00 -3.7908e-01 -5.9100e-01 - -1.3828e+00 -3.4816e-01 -5.9100e-01 - -1.3903e+00 -3.1707e-01 -5.9100e-01 - -1.3971e+00 -2.8582e-01 -5.9100e-01 - -1.4031e+00 -2.5442e-01 -5.9100e-01 - -1.4085e+00 -2.2290e-01 -5.9100e-01 - -1.4131e+00 -1.9127e-01 -5.9100e-01 - -1.4170e+00 -1.5954e-01 -5.9100e-01 - -1.4203e+00 -1.2773e-01 -5.9100e-01 - -1.4228e+00 -9.5850e-02 -5.9100e-01 - -1.4246e+00 -6.3927e-02 -5.9100e-01 - -1.4256e+00 -3.1972e-02 -5.9100e-01 - -1.4260e+00 1.7463e-16 -5.9100e-01 - -1.3685e+00 1.6759e-16 -6.9100e-01 - -1.3110e+00 1.6055e-16 -7.9100e-01 - -9.2702e-01 -9.2702e-01 -7.9100e-01 - -9.0823e-01 -9.4543e-01 -7.9100e-01 - -8.8909e-01 -9.6346e-01 -7.9100e-01 - -8.6958e-01 -9.8110e-01 -7.9100e-01 - -8.4972e-01 -9.9835e-01 -7.9100e-01 - -8.2952e-01 -1.0152e+00 -7.9100e-01 - -8.0899e-01 -1.0316e+00 -7.9100e-01 - -7.8813e-01 -1.0476e+00 -7.9100e-01 - -7.6696e-01 -1.0632e+00 -7.9100e-01 - -7.4547e-01 -1.0784e+00 -7.9100e-01 - -7.2369e-01 -1.0932e+00 -7.9100e-01 - -7.0161e-01 -1.1075e+00 -7.9100e-01 - -6.7926e-01 -1.1213e+00 -7.9100e-01 - -6.5663e-01 -1.1347e+00 -7.9100e-01 - -6.3373e-01 -1.1477e+00 -7.9100e-01 - -6.1058e-01 -1.1601e+00 -7.9100e-01 - -5.8718e-01 -1.1721e+00 -7.9100e-01 - -5.6355e-01 -1.1837e+00 -7.9100e-01 - -5.3969e-01 -1.1948e+00 -7.9100e-01 - -5.1562e-01 -1.2053e+00 -7.9100e-01 - -5.1562e-01 -1.2053e+00 -7.9100e-01 - -5.3823e-01 -1.2582e+00 -6.9100e-01 - -5.6085e-01 -1.3111e+00 -5.9100e-01 - -5.9010e-01 -1.2982e+00 -5.9100e-01 - -6.1906e-01 -1.2846e+00 -5.9100e-01 - -6.4770e-01 -1.2704e+00 -5.9100e-01 - -6.7602e-01 -1.2556e+00 -5.9100e-01 - -7.0400e-01 -1.2401e+00 -5.9100e-01 - -7.3163e-01 -1.2240e+00 -5.9100e-01 - -7.5889e-01 -1.2073e+00 -5.9100e-01 - -7.8577e-01 -1.1900e+00 -5.9100e-01 - -8.1225e-01 -1.1721e+00 -5.9100e-01 - -8.3832e-01 -1.1536e+00 -5.9100e-01 - -8.6398e-01 -1.1345e+00 -5.9100e-01 - -8.8919e-01 -1.1148e+00 -5.9100e-01 - -9.1397e-01 -1.0946e+00 -5.9100e-01 - -9.3828e-01 -1.0738e+00 -5.9100e-01 - -9.6212e-01 -1.0525e+00 -5.9100e-01 - -9.8547e-01 -1.0307e+00 -5.9100e-01 - -1.0083e+00 -1.0083e+00 -5.9100e-01 - -9.6768e-01 -9.6768e-01 -6.9100e-01 - -9.2702e-01 -9.2702e-01 -7.9100e-01 - -2.4083e-16 -1.3110e+00 -7.9100e-01 - 2.6300e-02 -1.3107e+00 -7.9100e-01 - 5.2589e-02 -1.3099e+00 -7.9100e-01 - 7.8857e-02 -1.3086e+00 -7.9100e-01 - 1.0509e-01 -1.3068e+00 -7.9100e-01 - 1.3129e-01 -1.3044e+00 -7.9100e-01 - 1.5743e-01 -1.3015e+00 -7.9100e-01 - 1.8351e-01 -1.2981e+00 -7.9100e-01 - 2.0951e-01 -1.2942e+00 -7.9100e-01 - 2.3543e-01 -1.2897e+00 -7.9100e-01 - 2.6125e-01 -1.2847e+00 -7.9100e-01 - 2.8697e-01 -1.2792e+00 -7.9100e-01 - 3.1258e-01 -1.2732e+00 -7.9100e-01 - 3.3806e-01 -1.2667e+00 -7.9100e-01 - 3.6340e-01 -1.2596e+00 -7.9100e-01 - 3.8859e-01 -1.2521e+00 -7.9100e-01 - 4.1363e-01 -1.2440e+00 -7.9100e-01 - 4.3851e-01 -1.2355e+00 -7.9100e-01 - 4.6320e-01 -1.2264e+00 -7.9100e-01 - 4.8771e-01 -1.2169e+00 -7.9100e-01 - 4.8771e-01 -1.2169e+00 -7.9100e-01 - 5.0910e-01 -1.2703e+00 -6.9100e-01 - 5.3049e-01 -1.3237e+00 -5.9100e-01 - 5.0068e-01 -1.3352e+00 -5.9100e-01 - 4.7062e-01 -1.3461e+00 -5.9100e-01 - 4.4032e-01 -1.3563e+00 -5.9100e-01 - 4.0980e-01 -1.3658e+00 -5.9100e-01 - 3.7908e-01 -1.3747e+00 -5.9100e-01 - 3.4816e-01 -1.3828e+00 -5.9100e-01 - 3.1707e-01 -1.3903e+00 -5.9100e-01 - 2.8582e-01 -1.3971e+00 -5.9100e-01 - 2.5442e-01 -1.4031e+00 -5.9100e-01 - 2.2290e-01 -1.4085e+00 -5.9100e-01 - 1.9127e-01 -1.4131e+00 -5.9100e-01 - 1.5954e-01 -1.4170e+00 -5.9100e-01 - 1.2773e-01 -1.4203e+00 -5.9100e-01 - 9.5850e-02 -1.4228e+00 -5.9100e-01 - 6.3927e-02 -1.4246e+00 -5.9100e-01 - 3.1972e-02 -1.4256e+00 -5.9100e-01 - -2.6195e-16 -1.4260e+00 -5.9100e-01 - -2.5139e-16 -1.3685e+00 -6.9100e-01 - -2.4083e-16 -1.3110e+00 -7.9100e-01 - 9.2702e-01 -9.2702e-01 -7.9100e-01 - 9.4543e-01 -9.0823e-01 -7.9100e-01 - 9.6346e-01 -8.8909e-01 -7.9100e-01 - 9.8110e-01 -8.6958e-01 -7.9100e-01 - 9.9835e-01 -8.4972e-01 -7.9100e-01 - 1.0152e+00 -8.2952e-01 -7.9100e-01 - 1.0316e+00 -8.0899e-01 -7.9100e-01 - 1.0476e+00 -7.8813e-01 -7.9100e-01 - 1.0632e+00 -7.6696e-01 -7.9100e-01 - 1.0784e+00 -7.4547e-01 -7.9100e-01 - 1.0932e+00 -7.2369e-01 -7.9100e-01 - 1.1075e+00 -7.0161e-01 -7.9100e-01 - 1.1213e+00 -6.7926e-01 -7.9100e-01 - 1.1347e+00 -6.5663e-01 -7.9100e-01 - 1.1477e+00 -6.3373e-01 -7.9100e-01 - 1.1601e+00 -6.1058e-01 -7.9100e-01 - 1.1721e+00 -5.8718e-01 -7.9100e-01 - 1.1837e+00 -5.6355e-01 -7.9100e-01 - 1.1948e+00 -5.3969e-01 -7.9100e-01 - 1.2053e+00 -5.1562e-01 -7.9100e-01 - 1.2053e+00 -5.1562e-01 -7.9100e-01 - 1.2582e+00 -5.3823e-01 -6.9100e-01 - 1.3111e+00 -5.6085e-01 -5.9100e-01 - 1.2982e+00 -5.9010e-01 -5.9100e-01 - 1.2846e+00 -6.1906e-01 -5.9100e-01 - 1.2704e+00 -6.4770e-01 -5.9100e-01 - 1.2556e+00 -6.7602e-01 -5.9100e-01 - 1.2401e+00 -7.0400e-01 -5.9100e-01 - 1.2240e+00 -7.3163e-01 -5.9100e-01 - 1.2073e+00 -7.5889e-01 -5.9100e-01 - 1.1900e+00 -7.8577e-01 -5.9100e-01 - 1.1721e+00 -8.1225e-01 -5.9100e-01 - 1.1536e+00 -8.3832e-01 -5.9100e-01 - 1.1345e+00 -8.6398e-01 -5.9100e-01 - 1.1148e+00 -8.8919e-01 -5.9100e-01 - 1.0946e+00 -9.1397e-01 -5.9100e-01 - 1.0738e+00 -9.3828e-01 -5.9100e-01 - 1.0525e+00 -9.6212e-01 -5.9100e-01 - 1.0307e+00 -9.8547e-01 -5.9100e-01 - 1.0083e+00 -1.0083e+00 -5.9100e-01 - 9.6768e-01 -9.6768e-01 -6.9100e-01 - 9.2702e-01 -9.2702e-01 -7.9100e-01 + 8 1 42 1.00 + 1.3110e+00 0.0000e+00 -7.9100e-01 + 1.3107e+00 2.6300e-02 -7.9100e-01 + 1.3099e+00 5.2589e-02 -7.9100e-01 + 1.3086e+00 7.8857e-02 -7.9100e-01 + 1.3068e+00 1.0509e-01 -7.9100e-01 + 1.3044e+00 1.3129e-01 -7.9100e-01 + 1.3015e+00 1.5743e-01 -7.9100e-01 + 1.2981e+00 1.8351e-01 -7.9100e-01 + 1.2942e+00 2.0951e-01 -7.9100e-01 + 1.2897e+00 2.3543e-01 -7.9100e-01 + 1.2847e+00 2.6125e-01 -7.9100e-01 + 1.2792e+00 2.8697e-01 -7.9100e-01 + 1.2732e+00 3.1258e-01 -7.9100e-01 + 1.2667e+00 3.3806e-01 -7.9100e-01 + 1.2596e+00 3.6340e-01 -7.9100e-01 + 1.2521e+00 3.8859e-01 -7.9100e-01 + 1.2440e+00 4.1363e-01 -7.9100e-01 + 1.2355e+00 4.3851e-01 -7.9100e-01 + 1.2264e+00 4.6320e-01 -7.9100e-01 + 1.2169e+00 4.8771e-01 -7.9100e-01 + 1.2169e+00 4.8771e-01 -7.9100e-01 + 1.2703e+00 5.0910e-01 -6.9100e-01 + 1.3237e+00 5.3049e-01 -5.9100e-01 + 1.3352e+00 5.0068e-01 -5.9100e-01 + 1.3461e+00 4.7062e-01 -5.9100e-01 + 1.3563e+00 4.4032e-01 -5.9100e-01 + 1.3658e+00 4.0980e-01 -5.9100e-01 + 1.3747e+00 3.7908e-01 -5.9100e-01 + 1.3828e+00 3.4816e-01 -5.9100e-01 + 1.3903e+00 3.1707e-01 -5.9100e-01 + 1.3971e+00 2.8582e-01 -5.9100e-01 + 1.4031e+00 2.5442e-01 -5.9100e-01 + 1.4085e+00 2.2290e-01 -5.9100e-01 + 1.4131e+00 1.9127e-01 -5.9100e-01 + 1.4170e+00 1.5954e-01 -5.9100e-01 + 1.4203e+00 1.2773e-01 -5.9100e-01 + 1.4228e+00 9.5850e-02 -5.9100e-01 + 1.4246e+00 6.3927e-02 -5.9100e-01 + 1.4256e+00 3.1972e-02 -5.9100e-01 + 1.4260e+00 0.0000e+00 -5.9100e-01 + 1.3685e+00 0.0000e+00 -6.9100e-01 + 1.3110e+00 0.0000e+00 -7.9100e-01 + 9.2702e-01 9.2702e-01 -7.9100e-01 + 9.0823e-01 9.4543e-01 -7.9100e-01 + 8.8909e-01 9.6346e-01 -7.9100e-01 + 8.6958e-01 9.8110e-01 -7.9100e-01 + 8.4972e-01 9.9835e-01 -7.9100e-01 + 8.2952e-01 1.0152e+00 -7.9100e-01 + 8.0899e-01 1.0316e+00 -7.9100e-01 + 7.8813e-01 1.0476e+00 -7.9100e-01 + 7.6696e-01 1.0632e+00 -7.9100e-01 + 7.4547e-01 1.0784e+00 -7.9100e-01 + 7.2369e-01 1.0932e+00 -7.9100e-01 + 7.0161e-01 1.1075e+00 -7.9100e-01 + 6.7926e-01 1.1213e+00 -7.9100e-01 + 6.5663e-01 1.1347e+00 -7.9100e-01 + 6.3373e-01 1.1477e+00 -7.9100e-01 + 6.1058e-01 1.1601e+00 -7.9100e-01 + 5.8718e-01 1.1721e+00 -7.9100e-01 + 5.6355e-01 1.1837e+00 -7.9100e-01 + 5.3969e-01 1.1948e+00 -7.9100e-01 + 5.1562e-01 1.2053e+00 -7.9100e-01 + 5.1562e-01 1.2053e+00 -7.9100e-01 + 5.3823e-01 1.2582e+00 -6.9100e-01 + 5.6085e-01 1.3111e+00 -5.9100e-01 + 5.9010e-01 1.2982e+00 -5.9100e-01 + 6.1906e-01 1.2846e+00 -5.9100e-01 + 6.4770e-01 1.2704e+00 -5.9100e-01 + 6.7602e-01 1.2556e+00 -5.9100e-01 + 7.0400e-01 1.2401e+00 -5.9100e-01 + 7.3163e-01 1.2240e+00 -5.9100e-01 + 7.5889e-01 1.2073e+00 -5.9100e-01 + 7.8577e-01 1.1900e+00 -5.9100e-01 + 8.1225e-01 1.1721e+00 -5.9100e-01 + 8.3832e-01 1.1536e+00 -5.9100e-01 + 8.6398e-01 1.1345e+00 -5.9100e-01 + 8.8919e-01 1.1148e+00 -5.9100e-01 + 9.1397e-01 1.0946e+00 -5.9100e-01 + 9.3828e-01 1.0738e+00 -5.9100e-01 + 9.6212e-01 1.0525e+00 -5.9100e-01 + 9.8547e-01 1.0307e+00 -5.9100e-01 + 1.0083e+00 1.0083e+00 -5.9100e-01 + 9.6768e-01 9.6768e-01 -6.9100e-01 + 9.2702e-01 9.2702e-01 -7.9100e-01 + 8.0276e-17 1.3110e+00 -7.9100e-01 + -2.6300e-02 1.3107e+00 -7.9100e-01 + -5.2589e-02 1.3099e+00 -7.9100e-01 + -7.8857e-02 1.3086e+00 -7.9100e-01 + -1.0509e-01 1.3068e+00 -7.9100e-01 + -1.3129e-01 1.3044e+00 -7.9100e-01 + -1.5743e-01 1.3015e+00 -7.9100e-01 + -1.8351e-01 1.2981e+00 -7.9100e-01 + -2.0951e-01 1.2942e+00 -7.9100e-01 + -2.3543e-01 1.2897e+00 -7.9100e-01 + -2.6125e-01 1.2847e+00 -7.9100e-01 + -2.8697e-01 1.2792e+00 -7.9100e-01 + -3.1258e-01 1.2732e+00 -7.9100e-01 + -3.3806e-01 1.2667e+00 -7.9100e-01 + -3.6340e-01 1.2596e+00 -7.9100e-01 + -3.8859e-01 1.2521e+00 -7.9100e-01 + -4.1363e-01 1.2440e+00 -7.9100e-01 + -4.3851e-01 1.2355e+00 -7.9100e-01 + -4.6320e-01 1.2264e+00 -7.9100e-01 + -4.8771e-01 1.2169e+00 -7.9100e-01 + -4.8771e-01 1.2169e+00 -7.9100e-01 + -5.0910e-01 1.2703e+00 -6.9100e-01 + -5.3049e-01 1.3237e+00 -5.9100e-01 + -5.0068e-01 1.3352e+00 -5.9100e-01 + -4.7062e-01 1.3461e+00 -5.9100e-01 + -4.4032e-01 1.3563e+00 -5.9100e-01 + -4.0980e-01 1.3658e+00 -5.9100e-01 + -3.7908e-01 1.3747e+00 -5.9100e-01 + -3.4816e-01 1.3828e+00 -5.9100e-01 + -3.1707e-01 1.3903e+00 -5.9100e-01 + -2.8582e-01 1.3971e+00 -5.9100e-01 + -2.5442e-01 1.4031e+00 -5.9100e-01 + -2.2290e-01 1.4085e+00 -5.9100e-01 + -1.9127e-01 1.4131e+00 -5.9100e-01 + -1.5954e-01 1.4170e+00 -5.9100e-01 + -1.2773e-01 1.4203e+00 -5.9100e-01 + -9.5850e-02 1.4228e+00 -5.9100e-01 + -6.3927e-02 1.4246e+00 -5.9100e-01 + -3.1972e-02 1.4256e+00 -5.9100e-01 + 8.7317e-17 1.4260e+00 -5.9100e-01 + 8.3796e-17 1.3685e+00 -6.9100e-01 + 8.0276e-17 1.3110e+00 -7.9100e-01 + -9.2702e-01 9.2702e-01 -7.9100e-01 + -9.4543e-01 9.0823e-01 -7.9100e-01 + -9.6346e-01 8.8909e-01 -7.9100e-01 + -9.8110e-01 8.6958e-01 -7.9100e-01 + -9.9835e-01 8.4972e-01 -7.9100e-01 + -1.0152e+00 8.2952e-01 -7.9100e-01 + -1.0316e+00 8.0899e-01 -7.9100e-01 + -1.0476e+00 7.8813e-01 -7.9100e-01 + -1.0632e+00 7.6696e-01 -7.9100e-01 + -1.0784e+00 7.4547e-01 -7.9100e-01 + -1.0932e+00 7.2369e-01 -7.9100e-01 + -1.1075e+00 7.0161e-01 -7.9100e-01 + -1.1213e+00 6.7926e-01 -7.9100e-01 + -1.1347e+00 6.5663e-01 -7.9100e-01 + -1.1477e+00 6.3373e-01 -7.9100e-01 + -1.1601e+00 6.1058e-01 -7.9100e-01 + -1.1721e+00 5.8718e-01 -7.9100e-01 + -1.1837e+00 5.6355e-01 -7.9100e-01 + -1.1948e+00 5.3969e-01 -7.9100e-01 + -1.2053e+00 5.1562e-01 -7.9100e-01 + -1.2053e+00 5.1562e-01 -7.9100e-01 + -1.2582e+00 5.3823e-01 -6.9100e-01 + -1.3111e+00 5.6085e-01 -5.9100e-01 + -1.2982e+00 5.9010e-01 -5.9100e-01 + -1.2846e+00 6.1906e-01 -5.9100e-01 + -1.2704e+00 6.4770e-01 -5.9100e-01 + -1.2556e+00 6.7602e-01 -5.9100e-01 + -1.2401e+00 7.0400e-01 -5.9100e-01 + -1.2240e+00 7.3163e-01 -5.9100e-01 + -1.2073e+00 7.5889e-01 -5.9100e-01 + -1.1900e+00 7.8577e-01 -5.9100e-01 + -1.1721e+00 8.1225e-01 -5.9100e-01 + -1.1536e+00 8.3832e-01 -5.9100e-01 + -1.1345e+00 8.6398e-01 -5.9100e-01 + -1.1148e+00 8.8919e-01 -5.9100e-01 + -1.0946e+00 9.1397e-01 -5.9100e-01 + -1.0738e+00 9.3828e-01 -5.9100e-01 + -1.0525e+00 9.6212e-01 -5.9100e-01 + -1.0307e+00 9.8547e-01 -5.9100e-01 + -1.0083e+00 1.0083e+00 -5.9100e-01 + -9.6768e-01 9.6768e-01 -6.9100e-01 + -9.2702e-01 9.2702e-01 -7.9100e-01 + -1.3110e+00 1.6055e-16 -7.9100e-01 + -1.3107e+00 -2.6300e-02 -7.9100e-01 + -1.3099e+00 -5.2589e-02 -7.9100e-01 + -1.3086e+00 -7.8857e-02 -7.9100e-01 + -1.3068e+00 -1.0509e-01 -7.9100e-01 + -1.3044e+00 -1.3129e-01 -7.9100e-01 + -1.3015e+00 -1.5743e-01 -7.9100e-01 + -1.2981e+00 -1.8351e-01 -7.9100e-01 + -1.2942e+00 -2.0951e-01 -7.9100e-01 + -1.2897e+00 -2.3543e-01 -7.9100e-01 + -1.2847e+00 -2.6125e-01 -7.9100e-01 + -1.2792e+00 -2.8697e-01 -7.9100e-01 + -1.2732e+00 -3.1258e-01 -7.9100e-01 + -1.2667e+00 -3.3806e-01 -7.9100e-01 + -1.2596e+00 -3.6340e-01 -7.9100e-01 + -1.2521e+00 -3.8859e-01 -7.9100e-01 + -1.2440e+00 -4.1363e-01 -7.9100e-01 + -1.2355e+00 -4.3851e-01 -7.9100e-01 + -1.2264e+00 -4.6320e-01 -7.9100e-01 + -1.2169e+00 -4.8771e-01 -7.9100e-01 + -1.2169e+00 -4.8771e-01 -7.9100e-01 + -1.2703e+00 -5.0910e-01 -6.9100e-01 + -1.3237e+00 -5.3049e-01 -5.9100e-01 + -1.3352e+00 -5.0068e-01 -5.9100e-01 + -1.3461e+00 -4.7062e-01 -5.9100e-01 + -1.3563e+00 -4.4032e-01 -5.9100e-01 + -1.3658e+00 -4.0980e-01 -5.9100e-01 + -1.3747e+00 -3.7908e-01 -5.9100e-01 + -1.3828e+00 -3.4816e-01 -5.9100e-01 + -1.3903e+00 -3.1707e-01 -5.9100e-01 + -1.3971e+00 -2.8582e-01 -5.9100e-01 + -1.4031e+00 -2.5442e-01 -5.9100e-01 + -1.4085e+00 -2.2290e-01 -5.9100e-01 + -1.4131e+00 -1.9127e-01 -5.9100e-01 + -1.4170e+00 -1.5954e-01 -5.9100e-01 + -1.4203e+00 -1.2773e-01 -5.9100e-01 + -1.4228e+00 -9.5850e-02 -5.9100e-01 + -1.4246e+00 -6.3927e-02 -5.9100e-01 + -1.4256e+00 -3.1972e-02 -5.9100e-01 + -1.4260e+00 1.7463e-16 -5.9100e-01 + -1.3685e+00 1.6759e-16 -6.9100e-01 + -1.3110e+00 1.6055e-16 -7.9100e-01 + -9.2702e-01 -9.2702e-01 -7.9100e-01 + -9.0823e-01 -9.4543e-01 -7.9100e-01 + -8.8909e-01 -9.6346e-01 -7.9100e-01 + -8.6958e-01 -9.8110e-01 -7.9100e-01 + -8.4972e-01 -9.9835e-01 -7.9100e-01 + -8.2952e-01 -1.0152e+00 -7.9100e-01 + -8.0899e-01 -1.0316e+00 -7.9100e-01 + -7.8813e-01 -1.0476e+00 -7.9100e-01 + -7.6696e-01 -1.0632e+00 -7.9100e-01 + -7.4547e-01 -1.0784e+00 -7.9100e-01 + -7.2369e-01 -1.0932e+00 -7.9100e-01 + -7.0161e-01 -1.1075e+00 -7.9100e-01 + -6.7926e-01 -1.1213e+00 -7.9100e-01 + -6.5663e-01 -1.1347e+00 -7.9100e-01 + -6.3373e-01 -1.1477e+00 -7.9100e-01 + -6.1058e-01 -1.1601e+00 -7.9100e-01 + -5.8718e-01 -1.1721e+00 -7.9100e-01 + -5.6355e-01 -1.1837e+00 -7.9100e-01 + -5.3969e-01 -1.1948e+00 -7.9100e-01 + -5.1562e-01 -1.2053e+00 -7.9100e-01 + -5.1562e-01 -1.2053e+00 -7.9100e-01 + -5.3823e-01 -1.2582e+00 -6.9100e-01 + -5.6085e-01 -1.3111e+00 -5.9100e-01 + -5.9010e-01 -1.2982e+00 -5.9100e-01 + -6.1906e-01 -1.2846e+00 -5.9100e-01 + -6.4770e-01 -1.2704e+00 -5.9100e-01 + -6.7602e-01 -1.2556e+00 -5.9100e-01 + -7.0400e-01 -1.2401e+00 -5.9100e-01 + -7.3163e-01 -1.2240e+00 -5.9100e-01 + -7.5889e-01 -1.2073e+00 -5.9100e-01 + -7.8577e-01 -1.1900e+00 -5.9100e-01 + -8.1225e-01 -1.1721e+00 -5.9100e-01 + -8.3832e-01 -1.1536e+00 -5.9100e-01 + -8.6398e-01 -1.1345e+00 -5.9100e-01 + -8.8919e-01 -1.1148e+00 -5.9100e-01 + -9.1397e-01 -1.0946e+00 -5.9100e-01 + -9.3828e-01 -1.0738e+00 -5.9100e-01 + -9.6212e-01 -1.0525e+00 -5.9100e-01 + -9.8547e-01 -1.0307e+00 -5.9100e-01 + -1.0083e+00 -1.0083e+00 -5.9100e-01 + -9.6768e-01 -9.6768e-01 -6.9100e-01 + -9.2702e-01 -9.2702e-01 -7.9100e-01 + -2.4083e-16 -1.3110e+00 -7.9100e-01 + 2.6300e-02 -1.3107e+00 -7.9100e-01 + 5.2589e-02 -1.3099e+00 -7.9100e-01 + 7.8857e-02 -1.3086e+00 -7.9100e-01 + 1.0509e-01 -1.3068e+00 -7.9100e-01 + 1.3129e-01 -1.3044e+00 -7.9100e-01 + 1.5743e-01 -1.3015e+00 -7.9100e-01 + 1.8351e-01 -1.2981e+00 -7.9100e-01 + 2.0951e-01 -1.2942e+00 -7.9100e-01 + 2.3543e-01 -1.2897e+00 -7.9100e-01 + 2.6125e-01 -1.2847e+00 -7.9100e-01 + 2.8697e-01 -1.2792e+00 -7.9100e-01 + 3.1258e-01 -1.2732e+00 -7.9100e-01 + 3.3806e-01 -1.2667e+00 -7.9100e-01 + 3.6340e-01 -1.2596e+00 -7.9100e-01 + 3.8859e-01 -1.2521e+00 -7.9100e-01 + 4.1363e-01 -1.2440e+00 -7.9100e-01 + 4.3851e-01 -1.2355e+00 -7.9100e-01 + 4.6320e-01 -1.2264e+00 -7.9100e-01 + 4.8771e-01 -1.2169e+00 -7.9100e-01 + 4.8771e-01 -1.2169e+00 -7.9100e-01 + 5.0910e-01 -1.2703e+00 -6.9100e-01 + 5.3049e-01 -1.3237e+00 -5.9100e-01 + 5.0068e-01 -1.3352e+00 -5.9100e-01 + 4.7062e-01 -1.3461e+00 -5.9100e-01 + 4.4032e-01 -1.3563e+00 -5.9100e-01 + 4.0980e-01 -1.3658e+00 -5.9100e-01 + 3.7908e-01 -1.3747e+00 -5.9100e-01 + 3.4816e-01 -1.3828e+00 -5.9100e-01 + 3.1707e-01 -1.3903e+00 -5.9100e-01 + 2.8582e-01 -1.3971e+00 -5.9100e-01 + 2.5442e-01 -1.4031e+00 -5.9100e-01 + 2.2290e-01 -1.4085e+00 -5.9100e-01 + 1.9127e-01 -1.4131e+00 -5.9100e-01 + 1.5954e-01 -1.4170e+00 -5.9100e-01 + 1.2773e-01 -1.4203e+00 -5.9100e-01 + 9.5850e-02 -1.4228e+00 -5.9100e-01 + 6.3927e-02 -1.4246e+00 -5.9100e-01 + 3.1972e-02 -1.4256e+00 -5.9100e-01 + -2.6195e-16 -1.4260e+00 -5.9100e-01 + -2.5139e-16 -1.3685e+00 -6.9100e-01 + -2.4083e-16 -1.3110e+00 -7.9100e-01 + 9.2702e-01 -9.2702e-01 -7.9100e-01 + 9.4543e-01 -9.0823e-01 -7.9100e-01 + 9.6346e-01 -8.8909e-01 -7.9100e-01 + 9.8110e-01 -8.6958e-01 -7.9100e-01 + 9.9835e-01 -8.4972e-01 -7.9100e-01 + 1.0152e+00 -8.2952e-01 -7.9100e-01 + 1.0316e+00 -8.0899e-01 -7.9100e-01 + 1.0476e+00 -7.8813e-01 -7.9100e-01 + 1.0632e+00 -7.6696e-01 -7.9100e-01 + 1.0784e+00 -7.4547e-01 -7.9100e-01 + 1.0932e+00 -7.2369e-01 -7.9100e-01 + 1.1075e+00 -7.0161e-01 -7.9100e-01 + 1.1213e+00 -6.7926e-01 -7.9100e-01 + 1.1347e+00 -6.5663e-01 -7.9100e-01 + 1.1477e+00 -6.3373e-01 -7.9100e-01 + 1.1601e+00 -6.1058e-01 -7.9100e-01 + 1.1721e+00 -5.8718e-01 -7.9100e-01 + 1.1837e+00 -5.6355e-01 -7.9100e-01 + 1.1948e+00 -5.3969e-01 -7.9100e-01 + 1.2053e+00 -5.1562e-01 -7.9100e-01 + 1.2053e+00 -5.1562e-01 -7.9100e-01 + 1.2582e+00 -5.3823e-01 -6.9100e-01 + 1.3111e+00 -5.6085e-01 -5.9100e-01 + 1.2982e+00 -5.9010e-01 -5.9100e-01 + 1.2846e+00 -6.1906e-01 -5.9100e-01 + 1.2704e+00 -6.4770e-01 -5.9100e-01 + 1.2556e+00 -6.7602e-01 -5.9100e-01 + 1.2401e+00 -7.0400e-01 -5.9100e-01 + 1.2240e+00 -7.3163e-01 -5.9100e-01 + 1.2073e+00 -7.5889e-01 -5.9100e-01 + 1.1900e+00 -7.8577e-01 -5.9100e-01 + 1.1721e+00 -8.1225e-01 -5.9100e-01 + 1.1536e+00 -8.3832e-01 -5.9100e-01 + 1.1345e+00 -8.6398e-01 -5.9100e-01 + 1.1148e+00 -8.8919e-01 -5.9100e-01 + 1.0946e+00 -9.1397e-01 -5.9100e-01 + 1.0738e+00 -9.3828e-01 -5.9100e-01 + 1.0525e+00 -9.6212e-01 -5.9100e-01 + 1.0307e+00 -9.8547e-01 -5.9100e-01 + 1.0083e+00 -1.0083e+00 -5.9100e-01 + 9.6768e-01 -9.6768e-01 -6.9100e-01 + 9.2702e-01 -9.2702e-01 -7.9100e-01 diff --git a/src/ForcingTerms/coil_geometries/mastu_rmpu.dat b/src/ForcingTerms/coil_geometries/mastu_rmpu.dat index 59d20c96d..ba2a4e14f 100644 --- a/src/ForcingTerms/coil_geometries/mastu_rmpu.dat +++ b/src/ForcingTerms/coil_geometries/mastu_rmpu.dat @@ -1,169 +1,169 @@ - 4 1 42 1.00 - 1.4180e+00 0.0000e+00 7.6000e-01 - 1.4177e+00 3.0026e-02 7.6000e-01 - 1.4167e+00 6.0039e-02 7.6000e-01 - 1.4151e+00 9.0025e-02 7.6000e-01 - 1.4129e+00 1.1997e-01 7.6000e-01 - 1.4101e+00 1.4986e-01 7.6000e-01 - 1.4066e+00 1.7969e-01 7.6000e-01 - 1.4024e+00 2.0943e-01 7.6000e-01 - 1.3977e+00 2.3908e-01 7.6000e-01 - 1.3923e+00 2.6862e-01 7.6000e-01 - 1.3863e+00 2.9805e-01 7.6000e-01 - 1.3797e+00 3.2733e-01 7.6000e-01 - 1.3725e+00 3.5648e-01 7.6000e-01 - 1.3646e+00 3.8546e-01 7.6000e-01 - 1.3561e+00 4.1427e-01 7.6000e-01 - 1.3471e+00 4.4289e-01 7.6000e-01 - 1.3374e+00 4.7132e-01 7.6000e-01 - 1.3271e+00 4.9953e-01 7.6000e-01 - 1.3162e+00 5.2752e-01 7.6000e-01 - 1.3162e+00 5.2752e-01 7.6000e-01 - 1.3487e+00 5.4054e-01 6.2950e-01 - 1.3812e+00 5.5356e-01 4.9900e-01 - 1.3926e+00 5.2419e-01 4.9900e-01 - 1.4034e+00 4.9458e-01 4.9900e-01 - 1.4136e+00 4.6475e-01 4.9900e-01 - 1.4231e+00 4.3472e-01 4.9900e-01 - 1.4320e+00 4.0449e-01 4.9900e-01 - 1.4402e+00 3.7407e-01 4.9900e-01 - 1.4478e+00 3.4349e-01 4.9900e-01 - 1.4548e+00 3.1276e-01 4.9900e-01 - 1.4611e+00 2.8188e-01 4.9900e-01 - 1.4667e+00 2.5088e-01 4.9900e-01 - 1.4717e+00 2.1977e-01 4.9900e-01 - 1.4760e+00 1.8856e-01 4.9900e-01 - 1.4797e+00 1.5726e-01 4.9900e-01 - 1.4827e+00 1.2589e-01 4.9900e-01 - 1.4850e+00 9.4469e-02 4.9900e-01 - 1.4867e+00 6.3003e-02 4.9900e-01 - 1.4877e+00 3.1509e-02 4.9900e-01 - 1.4880e+00 0.0000e+00 4.9900e-01 - 1.4530e+00 0.0000e+00 6.2950e-01 - 1.4180e+00 0.0000e+00 7.6000e-01 - 8.6827e-17 1.4180e+00 7.6000e-01 - -3.0026e-02 1.4177e+00 7.6000e-01 - -6.0039e-02 1.4167e+00 7.6000e-01 - -9.0025e-02 1.4151e+00 7.6000e-01 - -1.1997e-01 1.4129e+00 7.6000e-01 - -1.4986e-01 1.4101e+00 7.6000e-01 - -1.7969e-01 1.4066e+00 7.6000e-01 - -2.0943e-01 1.4024e+00 7.6000e-01 - -2.3908e-01 1.3977e+00 7.6000e-01 - -2.6862e-01 1.3923e+00 7.6000e-01 - -2.9805e-01 1.3863e+00 7.6000e-01 - -3.2733e-01 1.3797e+00 7.6000e-01 - -3.5648e-01 1.3725e+00 7.6000e-01 - -3.8546e-01 1.3646e+00 7.6000e-01 - -4.1427e-01 1.3561e+00 7.6000e-01 - -4.4289e-01 1.3471e+00 7.6000e-01 - -4.7132e-01 1.3374e+00 7.6000e-01 - -4.9953e-01 1.3271e+00 7.6000e-01 - -5.2752e-01 1.3162e+00 7.6000e-01 - -5.2752e-01 1.3162e+00 7.6000e-01 - -5.4054e-01 1.3487e+00 6.2950e-01 - -5.5356e-01 1.3812e+00 4.9900e-01 - -5.2419e-01 1.3926e+00 4.9900e-01 - -4.9458e-01 1.4034e+00 4.9900e-01 - -4.6475e-01 1.4136e+00 4.9900e-01 - -4.3472e-01 1.4231e+00 4.9900e-01 - -4.0449e-01 1.4320e+00 4.9900e-01 - -3.7407e-01 1.4402e+00 4.9900e-01 - -3.4349e-01 1.4478e+00 4.9900e-01 - -3.1276e-01 1.4548e+00 4.9900e-01 - -2.8188e-01 1.4611e+00 4.9900e-01 - -2.5088e-01 1.4667e+00 4.9900e-01 - -2.1977e-01 1.4717e+00 4.9900e-01 - -1.8856e-01 1.4760e+00 4.9900e-01 - -1.5726e-01 1.4797e+00 4.9900e-01 - -1.2589e-01 1.4827e+00 4.9900e-01 - -9.4469e-02 1.4850e+00 4.9900e-01 - -6.3003e-02 1.4867e+00 4.9900e-01 - -3.1509e-02 1.4877e+00 4.9900e-01 - 9.1114e-17 1.4880e+00 4.9900e-01 - 8.8971e-17 1.4530e+00 6.2950e-01 - 8.6827e-17 1.4180e+00 7.6000e-01 - -1.4180e+00 1.7365e-16 7.6000e-01 - -1.4177e+00 -3.0026e-02 7.6000e-01 - -1.4167e+00 -6.0039e-02 7.6000e-01 - -1.4151e+00 -9.0025e-02 7.6000e-01 - -1.4129e+00 -1.1997e-01 7.6000e-01 - -1.4101e+00 -1.4986e-01 7.6000e-01 - -1.4066e+00 -1.7969e-01 7.6000e-01 - -1.4024e+00 -2.0943e-01 7.6000e-01 - -1.3977e+00 -2.3908e-01 7.6000e-01 - -1.3923e+00 -2.6862e-01 7.6000e-01 - -1.3863e+00 -2.9805e-01 7.6000e-01 - -1.3797e+00 -3.2733e-01 7.6000e-01 - -1.3725e+00 -3.5648e-01 7.6000e-01 - -1.3646e+00 -3.8546e-01 7.6000e-01 - -1.3561e+00 -4.1427e-01 7.6000e-01 - -1.3471e+00 -4.4289e-01 7.6000e-01 - -1.3374e+00 -4.7132e-01 7.6000e-01 - -1.3271e+00 -4.9953e-01 7.6000e-01 - -1.3162e+00 -5.2752e-01 7.6000e-01 - -1.3162e+00 -5.2752e-01 7.6000e-01 - -1.3487e+00 -5.4054e-01 6.2950e-01 - -1.3812e+00 -5.5356e-01 4.9900e-01 - -1.3926e+00 -5.2419e-01 4.9900e-01 - -1.4034e+00 -4.9458e-01 4.9900e-01 - -1.4136e+00 -4.6475e-01 4.9900e-01 - -1.4231e+00 -4.3472e-01 4.9900e-01 - -1.4320e+00 -4.0449e-01 4.9900e-01 - -1.4402e+00 -3.7407e-01 4.9900e-01 - -1.4478e+00 -3.4349e-01 4.9900e-01 - -1.4548e+00 -3.1276e-01 4.9900e-01 - -1.4611e+00 -2.8188e-01 4.9900e-01 - -1.4667e+00 -2.5088e-01 4.9900e-01 - -1.4717e+00 -2.1977e-01 4.9900e-01 - -1.4760e+00 -1.8856e-01 4.9900e-01 - -1.4797e+00 -1.5726e-01 4.9900e-01 - -1.4827e+00 -1.2589e-01 4.9900e-01 - -1.4850e+00 -9.4469e-02 4.9900e-01 - -1.4867e+00 -6.3003e-02 4.9900e-01 - -1.4877e+00 -3.1509e-02 4.9900e-01 - -1.4880e+00 1.8223e-16 4.9900e-01 - -1.4530e+00 1.7794e-16 6.2950e-01 - -1.4180e+00 1.7365e-16 7.6000e-01 - -2.6048e-16 -1.4180e+00 7.6000e-01 - 3.0026e-02 -1.4177e+00 7.6000e-01 - 6.0039e-02 -1.4167e+00 7.6000e-01 - 9.0025e-02 -1.4151e+00 7.6000e-01 - 1.1997e-01 -1.4129e+00 7.6000e-01 - 1.4986e-01 -1.4101e+00 7.6000e-01 - 1.7969e-01 -1.4066e+00 7.6000e-01 - 2.0943e-01 -1.4024e+00 7.6000e-01 - 2.3908e-01 -1.3977e+00 7.6000e-01 - 2.6862e-01 -1.3923e+00 7.6000e-01 - 2.9805e-01 -1.3863e+00 7.6000e-01 - 3.2733e-01 -1.3797e+00 7.6000e-01 - 3.5648e-01 -1.3725e+00 7.6000e-01 - 3.8546e-01 -1.3646e+00 7.6000e-01 - 4.1427e-01 -1.3561e+00 7.6000e-01 - 4.4289e-01 -1.3471e+00 7.6000e-01 - 4.7132e-01 -1.3374e+00 7.6000e-01 - 4.9953e-01 -1.3271e+00 7.6000e-01 - 5.2752e-01 -1.3162e+00 7.6000e-01 - 5.2752e-01 -1.3162e+00 7.6000e-01 - 5.4054e-01 -1.3487e+00 6.2950e-01 - 5.5356e-01 -1.3812e+00 4.9900e-01 - 5.2419e-01 -1.3926e+00 4.9900e-01 - 4.9458e-01 -1.4034e+00 4.9900e-01 - 4.6475e-01 -1.4136e+00 4.9900e-01 - 4.3472e-01 -1.4231e+00 4.9900e-01 - 4.0449e-01 -1.4320e+00 4.9900e-01 - 3.7407e-01 -1.4402e+00 4.9900e-01 - 3.4349e-01 -1.4478e+00 4.9900e-01 - 3.1276e-01 -1.4548e+00 4.9900e-01 - 2.8188e-01 -1.4611e+00 4.9900e-01 - 2.5088e-01 -1.4667e+00 4.9900e-01 - 2.1977e-01 -1.4717e+00 4.9900e-01 - 1.8856e-01 -1.4760e+00 4.9900e-01 - 1.5726e-01 -1.4797e+00 4.9900e-01 - 1.2589e-01 -1.4827e+00 4.9900e-01 - 9.4469e-02 -1.4850e+00 4.9900e-01 - 6.3003e-02 -1.4867e+00 4.9900e-01 - 3.1509e-02 -1.4877e+00 4.9900e-01 - -2.7334e-16 -1.4880e+00 4.9900e-01 - -2.6691e-16 -1.4530e+00 6.2950e-01 - -2.6048e-16 -1.4180e+00 7.6000e-01 + 4 1 42 1.00 + 1.4180e+00 0.0000e+00 7.6000e-01 + 1.4177e+00 3.0026e-02 7.6000e-01 + 1.4167e+00 6.0039e-02 7.6000e-01 + 1.4151e+00 9.0025e-02 7.6000e-01 + 1.4129e+00 1.1997e-01 7.6000e-01 + 1.4101e+00 1.4986e-01 7.6000e-01 + 1.4066e+00 1.7969e-01 7.6000e-01 + 1.4024e+00 2.0943e-01 7.6000e-01 + 1.3977e+00 2.3908e-01 7.6000e-01 + 1.3923e+00 2.6862e-01 7.6000e-01 + 1.3863e+00 2.9805e-01 7.6000e-01 + 1.3797e+00 3.2733e-01 7.6000e-01 + 1.3725e+00 3.5648e-01 7.6000e-01 + 1.3646e+00 3.8546e-01 7.6000e-01 + 1.3561e+00 4.1427e-01 7.6000e-01 + 1.3471e+00 4.4289e-01 7.6000e-01 + 1.3374e+00 4.7132e-01 7.6000e-01 + 1.3271e+00 4.9953e-01 7.6000e-01 + 1.3162e+00 5.2752e-01 7.6000e-01 + 1.3162e+00 5.2752e-01 7.6000e-01 + 1.3487e+00 5.4054e-01 6.2950e-01 + 1.3812e+00 5.5356e-01 4.9900e-01 + 1.3926e+00 5.2419e-01 4.9900e-01 + 1.4034e+00 4.9458e-01 4.9900e-01 + 1.4136e+00 4.6475e-01 4.9900e-01 + 1.4231e+00 4.3472e-01 4.9900e-01 + 1.4320e+00 4.0449e-01 4.9900e-01 + 1.4402e+00 3.7407e-01 4.9900e-01 + 1.4478e+00 3.4349e-01 4.9900e-01 + 1.4548e+00 3.1276e-01 4.9900e-01 + 1.4611e+00 2.8188e-01 4.9900e-01 + 1.4667e+00 2.5088e-01 4.9900e-01 + 1.4717e+00 2.1977e-01 4.9900e-01 + 1.4760e+00 1.8856e-01 4.9900e-01 + 1.4797e+00 1.5726e-01 4.9900e-01 + 1.4827e+00 1.2589e-01 4.9900e-01 + 1.4850e+00 9.4469e-02 4.9900e-01 + 1.4867e+00 6.3003e-02 4.9900e-01 + 1.4877e+00 3.1509e-02 4.9900e-01 + 1.4880e+00 0.0000e+00 4.9900e-01 + 1.4530e+00 0.0000e+00 6.2950e-01 + 1.4180e+00 0.0000e+00 7.6000e-01 + 8.6827e-17 1.4180e+00 7.6000e-01 + -3.0026e-02 1.4177e+00 7.6000e-01 + -6.0039e-02 1.4167e+00 7.6000e-01 + -9.0025e-02 1.4151e+00 7.6000e-01 + -1.1997e-01 1.4129e+00 7.6000e-01 + -1.4986e-01 1.4101e+00 7.6000e-01 + -1.7969e-01 1.4066e+00 7.6000e-01 + -2.0943e-01 1.4024e+00 7.6000e-01 + -2.3908e-01 1.3977e+00 7.6000e-01 + -2.6862e-01 1.3923e+00 7.6000e-01 + -2.9805e-01 1.3863e+00 7.6000e-01 + -3.2733e-01 1.3797e+00 7.6000e-01 + -3.5648e-01 1.3725e+00 7.6000e-01 + -3.8546e-01 1.3646e+00 7.6000e-01 + -4.1427e-01 1.3561e+00 7.6000e-01 + -4.4289e-01 1.3471e+00 7.6000e-01 + -4.7132e-01 1.3374e+00 7.6000e-01 + -4.9953e-01 1.3271e+00 7.6000e-01 + -5.2752e-01 1.3162e+00 7.6000e-01 + -5.2752e-01 1.3162e+00 7.6000e-01 + -5.4054e-01 1.3487e+00 6.2950e-01 + -5.5356e-01 1.3812e+00 4.9900e-01 + -5.2419e-01 1.3926e+00 4.9900e-01 + -4.9458e-01 1.4034e+00 4.9900e-01 + -4.6475e-01 1.4136e+00 4.9900e-01 + -4.3472e-01 1.4231e+00 4.9900e-01 + -4.0449e-01 1.4320e+00 4.9900e-01 + -3.7407e-01 1.4402e+00 4.9900e-01 + -3.4349e-01 1.4478e+00 4.9900e-01 + -3.1276e-01 1.4548e+00 4.9900e-01 + -2.8188e-01 1.4611e+00 4.9900e-01 + -2.5088e-01 1.4667e+00 4.9900e-01 + -2.1977e-01 1.4717e+00 4.9900e-01 + -1.8856e-01 1.4760e+00 4.9900e-01 + -1.5726e-01 1.4797e+00 4.9900e-01 + -1.2589e-01 1.4827e+00 4.9900e-01 + -9.4469e-02 1.4850e+00 4.9900e-01 + -6.3003e-02 1.4867e+00 4.9900e-01 + -3.1509e-02 1.4877e+00 4.9900e-01 + 9.1114e-17 1.4880e+00 4.9900e-01 + 8.8971e-17 1.4530e+00 6.2950e-01 + 8.6827e-17 1.4180e+00 7.6000e-01 + -1.4180e+00 1.7365e-16 7.6000e-01 + -1.4177e+00 -3.0026e-02 7.6000e-01 + -1.4167e+00 -6.0039e-02 7.6000e-01 + -1.4151e+00 -9.0025e-02 7.6000e-01 + -1.4129e+00 -1.1997e-01 7.6000e-01 + -1.4101e+00 -1.4986e-01 7.6000e-01 + -1.4066e+00 -1.7969e-01 7.6000e-01 + -1.4024e+00 -2.0943e-01 7.6000e-01 + -1.3977e+00 -2.3908e-01 7.6000e-01 + -1.3923e+00 -2.6862e-01 7.6000e-01 + -1.3863e+00 -2.9805e-01 7.6000e-01 + -1.3797e+00 -3.2733e-01 7.6000e-01 + -1.3725e+00 -3.5648e-01 7.6000e-01 + -1.3646e+00 -3.8546e-01 7.6000e-01 + -1.3561e+00 -4.1427e-01 7.6000e-01 + -1.3471e+00 -4.4289e-01 7.6000e-01 + -1.3374e+00 -4.7132e-01 7.6000e-01 + -1.3271e+00 -4.9953e-01 7.6000e-01 + -1.3162e+00 -5.2752e-01 7.6000e-01 + -1.3162e+00 -5.2752e-01 7.6000e-01 + -1.3487e+00 -5.4054e-01 6.2950e-01 + -1.3812e+00 -5.5356e-01 4.9900e-01 + -1.3926e+00 -5.2419e-01 4.9900e-01 + -1.4034e+00 -4.9458e-01 4.9900e-01 + -1.4136e+00 -4.6475e-01 4.9900e-01 + -1.4231e+00 -4.3472e-01 4.9900e-01 + -1.4320e+00 -4.0449e-01 4.9900e-01 + -1.4402e+00 -3.7407e-01 4.9900e-01 + -1.4478e+00 -3.4349e-01 4.9900e-01 + -1.4548e+00 -3.1276e-01 4.9900e-01 + -1.4611e+00 -2.8188e-01 4.9900e-01 + -1.4667e+00 -2.5088e-01 4.9900e-01 + -1.4717e+00 -2.1977e-01 4.9900e-01 + -1.4760e+00 -1.8856e-01 4.9900e-01 + -1.4797e+00 -1.5726e-01 4.9900e-01 + -1.4827e+00 -1.2589e-01 4.9900e-01 + -1.4850e+00 -9.4469e-02 4.9900e-01 + -1.4867e+00 -6.3003e-02 4.9900e-01 + -1.4877e+00 -3.1509e-02 4.9900e-01 + -1.4880e+00 1.8223e-16 4.9900e-01 + -1.4530e+00 1.7794e-16 6.2950e-01 + -1.4180e+00 1.7365e-16 7.6000e-01 + -2.6048e-16 -1.4180e+00 7.6000e-01 + 3.0026e-02 -1.4177e+00 7.6000e-01 + 6.0039e-02 -1.4167e+00 7.6000e-01 + 9.0025e-02 -1.4151e+00 7.6000e-01 + 1.1997e-01 -1.4129e+00 7.6000e-01 + 1.4986e-01 -1.4101e+00 7.6000e-01 + 1.7969e-01 -1.4066e+00 7.6000e-01 + 2.0943e-01 -1.4024e+00 7.6000e-01 + 2.3908e-01 -1.3977e+00 7.6000e-01 + 2.6862e-01 -1.3923e+00 7.6000e-01 + 2.9805e-01 -1.3863e+00 7.6000e-01 + 3.2733e-01 -1.3797e+00 7.6000e-01 + 3.5648e-01 -1.3725e+00 7.6000e-01 + 3.8546e-01 -1.3646e+00 7.6000e-01 + 4.1427e-01 -1.3561e+00 7.6000e-01 + 4.4289e-01 -1.3471e+00 7.6000e-01 + 4.7132e-01 -1.3374e+00 7.6000e-01 + 4.9953e-01 -1.3271e+00 7.6000e-01 + 5.2752e-01 -1.3162e+00 7.6000e-01 + 5.2752e-01 -1.3162e+00 7.6000e-01 + 5.4054e-01 -1.3487e+00 6.2950e-01 + 5.5356e-01 -1.3812e+00 4.9900e-01 + 5.2419e-01 -1.3926e+00 4.9900e-01 + 4.9458e-01 -1.4034e+00 4.9900e-01 + 4.6475e-01 -1.4136e+00 4.9900e-01 + 4.3472e-01 -1.4231e+00 4.9900e-01 + 4.0449e-01 -1.4320e+00 4.9900e-01 + 3.7407e-01 -1.4402e+00 4.9900e-01 + 3.4349e-01 -1.4478e+00 4.9900e-01 + 3.1276e-01 -1.4548e+00 4.9900e-01 + 2.8188e-01 -1.4611e+00 4.9900e-01 + 2.5088e-01 -1.4667e+00 4.9900e-01 + 2.1977e-01 -1.4717e+00 4.9900e-01 + 1.8856e-01 -1.4760e+00 4.9900e-01 + 1.5726e-01 -1.4797e+00 4.9900e-01 + 1.2589e-01 -1.4827e+00 4.9900e-01 + 9.4469e-02 -1.4850e+00 4.9900e-01 + 6.3003e-02 -1.4867e+00 4.9900e-01 + 3.1509e-02 -1.4877e+00 4.9900e-01 + -2.7334e-16 -1.4880e+00 4.9900e-01 + -2.6691e-16 -1.4530e+00 6.2950e-01 + -2.6048e-16 -1.4180e+00 7.6000e-01 diff --git a/src/HDF5Schema.jl b/src/HDF5Schema.jl index b8b0333c7..0ad15083e 100644 --- a/src/HDF5Schema.jl +++ b/src/HDF5Schema.jl @@ -243,7 +243,7 @@ const MAIN_H5_ANNOTATIONS = [ "SurfaceGeometries/Plasma/z" => (; long_name="Cartesian z of plasma-surface point cloud", units="m"), "SurfaceGeometries/Wall/x" => (; long_name="Cartesian x of wall point cloud", units="m"), "SurfaceGeometries/Wall/y" => (; long_name="Cartesian y of wall point cloud", units="m"), - "SurfaceGeometries/Wall/z" => (; long_name="Cartesian z of wall point cloud", units="m"), + "SurfaceGeometries/Wall/z" => (; long_name="Cartesian z of wall point cloud", units="m") ] # Euler-Lagrange operator matrices: same wording per letter, Ideal/ and Kinetic/ variants. @@ -256,7 +256,7 @@ const _ELM_IDEAL_LETTERS = [ ("H", "Euler-Lagrange primitive coefficient matrix H"), ("F", "Euler-Lagrange derived coefficient matrix F"), ("K", "Euler-Lagrange derived coefficient matrix K"), - ("G", "Euler-Lagrange derived coefficient matrix G"), + ("G", "Euler-Lagrange derived coefficient matrix G") ] # The kinetic branch overwrites only A, B, C, K, G and adds f0; D, E, H, F are shared # unchanged from the ideal set and are not re-emitted. @@ -266,14 +266,19 @@ const _ELM_KINETIC_LETTERS = [ ("C", "Euler-Lagrange primitive coefficient matrix C"), ("K", "Euler-Lagrange derived coefficient matrix K"), ("G", "Euler-Lagrange derived coefficient matrix G"), - ("f0", "raw kinetic component matrix f0"), + ("f0", "raw kinetic component matrix f0") ] const ELM_H5_ANNOTATIONS = vcat( ["ForceFreeStates/EulerLagrangeMatrices/psi" => (; long_name="normalized poloidal flux ψ_N grid of the operator matrices", scale="psi")], - ["ForceFreeStates/EulerLagrangeMatrices/Ideal/$l" => - (; long_name="ideal " * d, dims=("psi", "mode_row", "mode_col"), attach=(1 => "ForceFreeStates/EulerLagrangeMatrices/psi",)) for (l, d) in _ELM_IDEAL_LETTERS], - ["ForceFreeStates/EulerLagrangeMatrices/Kinetic/$l" => - (; long_name="kinetic-modified " * d, dims=("psi", "mode_row", "mode_col"), attach=(1 => "ForceFreeStates/EulerLagrangeMatrices/psi",)) for (l, d) in _ELM_KINETIC_LETTERS] + [ + "ForceFreeStates/EulerLagrangeMatrices/Ideal/$l" => + (; long_name="ideal " * d, dims=("psi", "mode_row", "mode_col"), attach=(1 => "ForceFreeStates/EulerLagrangeMatrices/psi",)) for (l, d) in _ELM_IDEAL_LETTERS + ], + [ + "ForceFreeStates/EulerLagrangeMatrices/Kinetic/$l" => + (; long_name="kinetic-modified " * d, dims=("psi", "mode_row", "mode_col"), attach=(1 => "ForceFreeStates/EulerLagrangeMatrices/psi",)) for + (l, d) in _ELM_KINETIC_LETTERS + ] ) """ diff --git a/src/InnerLayer/GGJ/Ray.jl b/src/InnerLayer/GGJ/Ray.jl index cb188f4aa..3abbc4f46 100644 --- a/src/InnerLayer/GGJ/Ray.jl +++ b/src/InnerLayer/GGJ/Ray.jl @@ -943,8 +943,6 @@ end npc=8, certify_rtol=1e-3, kwargs...) -> (; Δ, x, Ψ, Ξ, dψdx, rescale, certΔ) -Rotated-ray implementation of the [`solve_inner_profile`](@ref) interface. The -certified `Δ` comes from the optimal-contour solve at θ = arg(Q)/4 (robust for |Q| ≳ 1, where real-axis methods drift); the profiles come from a θ = 0 re-solve on the real axis, valid at physical (RPEC) |Q| since the on-axis pseudo-resonance is a regular point resolved by the BVP refinement. The diff --git a/src/InnerLayer/InnerLayerInterface.jl b/src/InnerLayer/InnerLayerInterface.jl index 52e1b36ea..5ad7dedaf 100644 --- a/src/InnerLayer/InnerLayerInterface.jl +++ b/src/InnerLayer/InnerLayerInterface.jl @@ -87,13 +87,13 @@ tuple with at least: - `Δ` — the same `(Δ_odd, Δ_even)` matching data as [`solve_inner`](@ref) - `x` — real ascending grid in the model's stretched inner coordinate, - `x ≥ 0` with the rational surface at `x = 0` + `x ≥ 0` with the rational surface at `x = 0` - `Ψ`, `Ξ` — `length(x) × 2` profiles, columns (odd, even) parity, in the - model's inner normalization: `Ψ` the normal-field - (reconnected-flux) variable, `Ξ` the displacement + model's inner normalization: `Ψ` the normal-field + (reconnected-flux) variable, `Ξ` the displacement - `dψdx` — conversion to poloidal-flux distance, `δψ = dψdx · x` - `rescale` — amplitude factor converting the inner-normalized profiles to - the outer δψ-normalized convention (companion of the Δ rescale) + the outer δψ-normalized convention (companion of the Δ rescale) Concrete models may return additional diagnostic fields (e.g. a solve-quality certificate). Solver-knob keywords are model-specific. diff --git a/src/InnerLayer/SLAYER/LayerInputs.jl b/src/InnerLayer/SLAYER/LayerInputs.jl index 96177903d..b25faa154 100644 --- a/src/InnerLayer/SLAYER/LayerInputs.jl +++ b/src/InnerLayer/SLAYER/LayerInputs.jl @@ -87,11 +87,15 @@ profiles, without an intermediate file round-trip. physical field, so passing it as a scalar is almost always wrong. - `mu_i` -- ion mass in proton-mass units (default `2.0` for D). + - `zeff` -- effective charge (default `1.0`). + - `chi_perp` -- perpendicular heat diffusivity [m²/s]. Scalar or a callable of `psi` (default `1.0`). + - `chi_tor` -- toroidal heat diffusivity [m²/s]. Scalar or a callable of `psi` (default `1.0`). + - `dr_val` -- resistive interchange index `D_R = E + F + H²` (Glasser-Greene-Johnson 1975) feeding the critical-Δ formulas (`:lar`, `:rfitzp`, `:toroidal`). When `nothing` (default), Julia @@ -106,6 +110,7 @@ profiles, without an intermediate file round-trip. NOT the Mercier index `D_I = E + F + H − 1/4`. The two differ by `(H − 1/2)²`, which is non-trivial on shaped equilibria (~factor 3 on DIII-D); this code uses the physically correct `D_R`. + - `dgeo_val` -- Connor 2015 (PPCF 57 065001) Eq. 59 geometric factor used by `dc_type=:toroidal`. When `nothing` (default), an error is raised if `dc_type=:toroidal` is also requested — the auto-derived @@ -113,15 +118,19 @@ profiles, without an intermediate file round-trip. doesn't currently expose. Pass a scalar / vector / callable to use a prescribed value. (For `dc_type=:rfitzp` and `:lar`, dgeo_val is not consulted.) + - `dc_type` -- `:none` (default), `:lar`, `:rfitzp`, or `:toroidal`. + - `theta` -- poloidal angle at which to measure minor radius (default `0.0`, outboard midplane). + - `resistivity_model` -- `SauterNeoModel()` (default), `RedlNeoModel()`, `SpitzerModel()`, or `SpitzerHarmModel()` (legacy Fitzpatrick σ_∥). Sets the η entering τ_R = μ₀r_s²/η. With a neoclassical model, `f_trap` and ν*_e are taken from the surface's `ResistGeometry` if populated (via `ForceFreeStates.resist_eval_all!`), otherwise fall back to the ε-only Lin-Liu-Miller form and `rs/R_0` aspect ratio. + - `lnLambda_form` -- Coulomb-log form passed through to `slayer_parameters` (default `:nrl`; `:wesson` + `SpitzerHarmModel()` reproduces legacy SLAYER exactly). diff --git a/src/InnerLayer/SLAYER/LayerParameters.jl b/src/InnerLayer/SLAYER/LayerParameters.jl index 5dbf9163f..8e3c17fb1 100644 --- a/src/InnerLayer/SLAYER/LayerParameters.jl +++ b/src/InnerLayer/SLAYER/LayerParameters.jl @@ -20,32 +20,32 @@ Fitzpatrick two-fluid drift-MHD SLAYER inner-layer model (Fitzpatrick de-normalization. The parametrization uses `P_perp`, `P_tor`, and `D_norm` (not the older `pr`/`pe`/`ds` set). -| field | meaning | -|:---------- |:----------------------------------------------------------------- | -| `ising` | Singular-surface index (traceability only) | -| `m`, `n` | Poloidal / toroidal mode numbers at this surface | -| `tau` | T_i / T_e | -| `lu` | Lundquist number S = τ_R / τ_H | -| `c_beta` | Compressibility √(β_local / (1 + β_local)) | -| `D_norm` | (d_β/r_s) · S^(1/3) · √(τ/(1+τ)) (Fitzpatrick normalized scale) | -| `P_perp` | Perpendicular Prandtl number τ_R / τ_⊥ | -| `P_tor` | Toroidal-direction Prandtl number τ_R / τ_‖tor | -| `Q_e` | Normalized electron diamagnetic: −tauk · ω_*e | -| `Q_i` | Normalized ion diamagnetic: −tauk · ω_*i | -| `iota_e` | Q_e / (Q_e − Q_i) | -| `tauk` | Q-conversion factor S^(1/3) · τ_H [s] — multiplies ω to get Q | -| `tau_r` | Resistive diffusion time [s] | -| `delta_n` | Δ-normalization factor S^(1/3) / r_s [m⁻¹] | -| `rs` | Minor radius at this surface [m] | -| `R0` | Major radius [m] | -| `bt` | Toroidal field [T] | -| `sval_r` | r-based magnetic shear r_s · (dq/dr) / q (Fitzpatrick convention) | +| field | meaning | +|:---------- |:--------------------------------------------------------------------------------------------------------------- | +| `ising` | Singular-surface index (traceability only) | +| `m`, `n` | Poloidal / toroidal mode numbers at this surface | +| `tau` | T_i / T_e | +| `lu` | Lundquist number S = τ_R / τ_H | +| `c_beta` | Compressibility √(β_local / (1 + β_local)) | +| `D_norm` | (d_β/r_s) · S^(1/3) · √(τ/(1+τ)) (Fitzpatrick normalized scale) | +| `P_perp` | Perpendicular Prandtl number τ_R / τ_⊥ | +| `P_tor` | Toroidal-direction Prandtl number τ_R / τ_‖tor | +| `Q_e` | Normalized electron diamagnetic: −tauk · ω_*e | +| `Q_i` | Normalized ion diamagnetic: −tauk · ω_*i | +| `iota_e` | Q_e / (Q_e − Q_i) | +| `tauk` | Q-conversion factor S^(1/3) · τ_H [s] — multiplies ω to get Q | +| `tau_r` | Resistive diffusion time [s] | +| `delta_n` | Δ-normalization factor S^(1/3) / r_s [m⁻¹] | +| `rs` | Minor radius at this surface [m] | +| `R0` | Major radius [m] | +| `bt` | Toroidal field [T] | +| `sval_r` | r-based magnetic shear r_s · (dq/dr) / q (Fitzpatrick convention) | | `dr_val` | Resistive interchange D_R = E + F + H² (critical-Δ input; auto-derived from GGJ coefficients unless overridden) | -| `dgeo_val` | Connor-Hastie-Helander 2015 Eq. 59 geometric factor (0 unless supplied) | -| `eta` | Parallel resistivity entering τ_R = μ₀r_s²/η [Ω·m] | -| `d_beta` | Beta-weighted ion length scale c_β · d_i [m] | -| `dc_tmp` | Critical-Δ offset from chi_parallel matching | -| `dc_type` | Selector for `dc_tmp` formula | +| `dgeo_val` | Connor-Hastie-Helander 2015 Eq. 59 geometric factor (0 unless supplied) | +| `eta` | Parallel resistivity entering τ_R = μ₀r_s²/η [Ω·m] | +| `d_beta` | Beta-weighted ion length scale c_β · d_i [m] | +| `dc_tmp` | Critical-Δ offset from chi_parallel matching | +| `dc_type` | Selector for `dc_tmp` formula | The complex normalized growth rate `Q = ω + iγ` is **not** stored here; it is passed as a separate argument to `solve_inner`. diff --git a/src/KineticForces/BounceAveraging.jl b/src/KineticForces/BounceAveraging.jl index 63a59aedc..5dddae01d 100644 --- a/src/KineticForces/BounceAveraging.jl +++ b/src/KineticForces/BounceAveraging.jl @@ -31,7 +31,7 @@ struct BounceData # For matrix path (nothing if scalar-only): packed layout (nlmda, nqty_matrix(mpert)). # Consumer fills into fbnce_data[:, 3:end] by direct copy. See `nqty_matrix` for # the 3-Hermitian-triangle + 3-full-block packing (Logan 2015 Eqs 7.30–7.35). - wmats_vs_lambda::Union{Nothing, Matrix{ComplexF64}} + wmats_vs_lambda::Union{Nothing,Matrix{ComplexF64}} end @@ -44,13 +44,19 @@ end # the full mpert² for the three non-Hermitian blocks. Block packing order: # A-tri, D-tri, H-tri, B-full, C-full, E-full. -"""Number of packed complex entries per λ for the 6 kinetic matrices.""" +""" +Number of packed complex entries per λ for the 6 kinetic matrices. +""" @inline nqty_matrix(mpert::Int) = 3 * (mpert * (mpert + 1)) ÷ 2 + 3 * mpert^2 -"""Upper-triangle index (1 ≤ i ≤ j ≤ mpert) within a triangular block.""" +""" +Upper-triangle index (1 ≤ i ≤ j ≤ mpert) within a triangular block. +""" @inline _tri_idx(i::Int, j::Int) = (j * (j - 1)) ÷ 2 + i -"""Full-block index (column-major) within a non-Hermitian block.""" +""" +Full-block index (column-major) within a non-Hermitian block. +""" @inline _full_idx(i::Int, j::Int, mpert::Int) = (j - 1) * mpert + i @@ -65,14 +71,16 @@ Generate a grid with power-law concentration near endpoints. Port of Fortran `powspace_sub` from equil/grid.f90. # Arguments -- `xmin, xmax`: Grid bounds -- `pow::Int`: Power of grid concentration (higher = more refined near edges) -- `num::Int`: Number of grid points -- `endpoints::String`: Where to concentrate: "lower", "upper", or "both" + + - `xmin, xmax`: Grid bounds + - `pow::Int`: Power of grid concentration (higher = more refined near edges) + - `num::Int`: Number of grid points + - `endpoints::String`: Where to concentrate: "lower", "upper", or "both" # Returns -- `points::Vector{Float64}`: Grid point locations -- `weights::Vector{Float64}`: Derivatives dx/dnorm (integration weights) + + - `points::Vector{Float64}`: Grid point locations + - `weights::Vector{Float64}`: Derivatives dx/dnorm (integration weights) """ function powspace(xmin::Float64, xmax::Float64, pow::Int, num::Int, endpoints::String) if xmax <= xmin @@ -81,11 +89,11 @@ function powspace(xmin::Float64, xmax::Float64, pow::Int, num::Int, endpoints::S # Linear base grid in [-1,1], [0,1], or [-1,0] x = if endpoints == "lower" - collect(range(-1.0, 0.0, length=num)) + collect(range(-1.0, 0.0; length=num)) elseif endpoints == "upper" - collect(range(0.0, 1.0, length=num)) + collect(range(0.0, 1.0; length=num)) elseif endpoints == "both" - collect(range(-1.0, 1.0, length=num)) + collect(range(-1.0, 1.0; length=num)) else error("powspace: invalid endpoints '$endpoints' — use lower, upper, or both") end @@ -160,31 +168,33 @@ needed by the pitch-angle quadrature. Ports Fortran torque.F90 lines 530-816 (GAR branch). # Arguments -- `psi`: Normalized poloidal flux -- `n`: Toroidal mode number -- `l`: Bounce harmonic number -- `q`: Safety factor at this ψ -- `bo`: On-axis toroidal field [T] -- `bmax, bmin`: Max/min of B(θ) at this ψ -- `theta_bmax`: θ location of Bmax (nodal knot; the passing-transit start) -- `tspl`: Periodic poloidal interpolant: tspl(θ) → [B, dB/dψ, dB/dθ, J, dJ/dψ] -- `B_extrap`: Endpoint-fit (non-periodic) cubic of B(θ) used for v_par and the - bounce-point roots (the Fortran `vspl` equivalent) -- `mfac`: Poloidal mode numbers [mlow:mhigh] -- `chi1`: 2π·ψ₀ flux normalization -- `ro`: Major radius [m] -- `dbob_m_f`: δB/B Fourier modes at this ψ (ComplexF64 vector, length mpert) -- `divx_m_f`: ∇·ξ⊥ Fourier modes at this ψ (ComplexF64 vector, length mpert) -- `divxfac, wdfac`: Scaling factors -- `mass`: Particle mass [kg] -- `chrg`: Particle charge [C] -- `T_s`: Species temperature at this ψ [J] -- `method`: Method string (first char: f/t/p determines λ range) + + - `psi`: Normalized poloidal flux + - `n`: Toroidal mode number + - `l`: Bounce harmonic number + - `q`: Safety factor at this ψ + - `bo`: On-axis toroidal field [T] + - `bmax, bmin`: Max/min of B(θ) at this ψ + - `theta_bmax`: θ location of Bmax (nodal knot; the passing-transit start) + - `tspl`: Periodic poloidal interpolant: tspl(θ) → [B, dB/dψ, dB/dθ, J, dJ/dψ] + - `B_extrap`: Endpoint-fit (non-periodic) cubic of B(θ) used for v_par and the + bounce-point roots (the Fortran `vspl` equivalent) + - `mfac`: Poloidal mode numbers [mlow:mhigh] + - `chi1`: 2π·ψ₀ flux normalization + - `ro`: Major radius [m] + - `dbob_m_f`: δB/B Fourier modes at this ψ (ComplexF64 vector, length mpert) + - `divx_m_f`: ∇·ξ⊥ Fourier modes at this ψ (ComplexF64 vector, length mpert) + - `divxfac, wdfac`: Scaling factors + - `mass`: Particle mass [kg] + - `chrg`: Particle charge [C] + - `T_s`: Species temperature at this ψ [J] + - `method`: Method string (first char: f/t/p determines λ range) # Keyword Arguments -- `nlmda`: Number of pitch angle grid points (default 128, matching Fortran pentrc nlmda) -- `ntheta`: Number of poloidal grid points per bounce (default 128) -- `smat, tmat, xmat, ymat, zmat`: Geometric matrices (mpert×mpert) for kinetic matrix path + + - `nlmda`: Number of pitch angle grid points (default 128, matching Fortran pentrc nlmda) + - `ntheta`: Number of poloidal grid points per bounce (default 128) + - `smat, tmat, xmat, ymat, zmat`: Geometric matrices (mpert×mpert) for kinetic matrix path """ function compute_bounce_data( psi::Float64, n::Int, l::Int, q::Float64, @@ -262,7 +272,7 @@ function compute_bounce_data( end return BounceData(nlmda, lambda, dlambda, sigma_arr, - wb_arr, wd_arr, dJdJ_arr, wmats_arr) + wb_arr, wd_arr, dJdJ_arr, wmats_arr) end @@ -275,23 +285,24 @@ Per-surface scratch for the bounce-averaging inner loops, allocated once in partially are `fill!`-reset per λ. ## Fields -- `g_wb::Vector{Float64}`: length `ntheta` — bounce-action integrand samples -- `g_wd::Vector{Float64}`: length `ntheta` — drift integrand samples -- `cum_wb_arr::Vector{Float64}`: length `ntheta` — cumulative bounce-action integral -- `jvtheta::Vector{ComplexF64}`: length `ntheta` — action integrand -- `bj_samples::Vector{ComplexF64}`: length `ntheta` — action bounce-integral samples -- `wsamp::Vector{ComplexF64}`: length `ntheta` — per-mode W bounce-integral samples -- `wmu_mt::Matrix{ComplexF64}`: `mpert × ntheta` — W_μ per θ -- `wen_mt::Matrix{ComplexF64}`: `mpert × ntheta` — W_E per θ -- `expm::Vector{ComplexF64}`: length `mpert` — Fourier basis at a θ -- `pl::Vector{ComplexF64}`: length `ntheta` — bounce phase factor -- `wmu_ba::Vector{ComplexF64}`: length `mpert` — bounce-averaged W_μ -- `wen_ba::Vector{ComplexF64}`: length `mpert` — bounce-averaged W_E -- `wmats_lmda::Vector{ComplexF64}`: length `nqty_matrix(mpert)` — packed W outer products -- `tspl_f::Vector{Float64}`: length 5 — in-place tspl(θ) evaluation -- `int_w::Vector{Float64}`, `cumint_W::Matrix{Float64}`: precomputed exact-cubic - quadrature weights on the fixed unit θ-grid (`∫ = int_w·y`, `cumulative = cumint_W·y`); - shared read-only across surfaces, see `_quadrature_weights` + + - `g_wb::Vector{Float64}`: length `ntheta` — bounce-action integrand samples + - `g_wd::Vector{Float64}`: length `ntheta` — drift integrand samples + - `cum_wb_arr::Vector{Float64}`: length `ntheta` — cumulative bounce-action integral + - `jvtheta::Vector{ComplexF64}`: length `ntheta` — action integrand + - `bj_samples::Vector{ComplexF64}`: length `ntheta` — action bounce-integral samples + - `wsamp::Vector{ComplexF64}`: length `ntheta` — per-mode W bounce-integral samples + - `wmu_mt::Matrix{ComplexF64}`: `mpert × ntheta` — W_μ per θ + - `wen_mt::Matrix{ComplexF64}`: `mpert × ntheta` — W_E per θ + - `expm::Vector{ComplexF64}`: length `mpert` — Fourier basis at a θ + - `pl::Vector{ComplexF64}`: length `ntheta` — bounce phase factor + - `wmu_ba::Vector{ComplexF64}`: length `mpert` — bounce-averaged W_μ + - `wen_ba::Vector{ComplexF64}`: length `mpert` — bounce-averaged W_E + - `wmats_lmda::Vector{ComplexF64}`: length `nqty_matrix(mpert)` — packed W outer products + - `tspl_f::Vector{Float64}`: length 5 — in-place tspl(θ) evaluation + - `int_w::Vector{Float64}`, `cumint_W::Matrix{Float64}`: precomputed exact-cubic + quadrature weights on the fixed unit θ-grid (`∫ = int_w·y`, `cumulative = cumint_W·y`); + shared read-only across surfaces, see `_quadrature_weights` """ struct BounceScratch g_wb::Vector{Float64} @@ -330,7 +341,7 @@ function BounceScratch(ntheta::Int, mpert::Int) Vector{ComplexF64}(undef, nqty_matrix(mpert)), Vector{Float64}(undef, 5), int_w, - cumint_W, + cumint_W ) end @@ -351,7 +362,7 @@ fitting and integrating each sample vector directly, but reducing the per-λ hot function _quadrature_weights(ntheta::Int) lock(_QUAD_WEIGHTS_LOCK) do get!(_QUAD_WEIGHTS, ntheta) do - xs = collect(range(0.0, 1.0, length=ntheta)) + xs = collect(range(0.0, 1.0; length=ntheta)) int_w = zeros(Float64, ntheta) cumint_W = zeros(Float64, ntheta, ntheta) ej = zeros(Float64, ntheta) @@ -384,12 +395,12 @@ function _build_lambda_grid(method_char::Char, lmdatpb::Float64, lmdamax::Float6 if method_char == 't' # Trapped only: λ ∈ (lmdatpb, lmdamax), exclude endpoints pts_inc, wts_inc = powspace(lmdatpb, lmdamax, 1, 2 + nlmda, "both") - return pts_inc[2:end-1], wts_inc[2:end-1] + return pts_inc[2:(end-1)], wts_inc[2:(end-1)] elseif method_char == 'p' # Passing only: λ ∈ (lmdamin, lmdatpb), exclude endpoints pts_inc, wts_inc = powspace(lmdamin, lmdatpb, 1, 2 + nlmda, "both") - return pts_inc[2:end-1], wts_inc[2:end-1] + return pts_inc[2:(end-1)], wts_inc[2:(end-1)] else # 'f' = full if lmdatpb ≈ lmdamax @@ -401,8 +412,8 @@ function _build_lambda_grid(method_char::Char, lmdatpb::Float64, lmdamax::Float6 pts_p, wts_p = powspace(lmdamin, lmdatpb, 2, 2 + nhalf_p, "upper") pts_t, wts_t = powspace(lmdatpb, lmdamax, 2, 2 + nhalf_t, "lower") # Exclude boundary points - lambda = vcat(pts_p[2:end-1], pts_t[2:end-1]) - dlambda = vcat(wts_p[2:end-1], wts_t[2:end-1]) + lambda = vcat(pts_p[2:(end-1)], pts_t[2:(end-1)]) + dlambda = vcat(wts_p[2:(end-1)], wts_t[2:(end-1)]) return lambda, dlambda end end @@ -538,7 +549,7 @@ function _bounce_integrate( tspl_f = scr.tspl_f expm = scr.expm - for i in 2:ntheta-1 # Edge weights are 0 from powspace + for i in 2:(ntheta-1) # Edge weights are 0 from powspace θ = tdt_pts[i] dt = tdt_wts[i] θmod = mod(θ, 1.0) @@ -595,8 +606,8 @@ function _bounce_integrate( # Action integrand phase = cis(-twopi * n * q * (θ - theta0)) jvtheta[i] = dt * jac * B_val * - (divx * sqrt_vpar + dbob * (1.0 - 1.5 * lmda * B_val / bo) / sqrt_vpar) * - phase + (divx * sqrt_vpar + dbob * (1.0 - 1.5 * lmda * B_val / bo) / sqrt_vpar) * + phase # W vectors for matrix path if do_matrices @@ -611,9 +622,9 @@ function _bounce_integrate( # Smooth backfill for points zeroed before a restart. Exact equality with # 0.0 is safe: the restart branch set these entries with fill!(…, 0.0). if i >= 3 && g_wb[i-1] == 0.0 - fill!(view(g_wb, 3:i-1), g_wb[i]) - fill!(view(g_wd, 3:i-1), g_wd[i]) - fill!(view(jvtheta, 2:i-1), jvtheta[i]) + fill!(view(g_wb, 3:(i-1)), g_wb[i]) + fill!(view(g_wd, 3:(i-1)), g_wd[i]) + fill!(view(jvtheta, 2:(i-1)), jvtheta[i]) end end @@ -698,32 +709,32 @@ function _bounce_integrate( # A (Hermitian): upper triangle of W_Z†W_Z, rank-1 → conj(wz[i])·wz[j]. off = 0 @inbounds for j in 1:mpert, i in 1:j - wmats_lmda[off + _tri_idx(i, j)] = conj(wz[i]) * wz[j] * scale + wmats_lmda[off+_tri_idx(i, j)] = conj(wz[i]) * wz[j] * scale end off += Mu # D (Hermitian): upper triangle of W_X†W_X. @inbounds for j in 1:mpert, i in 1:j - wmats_lmda[off + _tri_idx(i, j)] = conj(wx[i]) * wx[j] * scale + wmats_lmda[off+_tri_idx(i, j)] = conj(wx[i]) * wx[j] * scale end off += Mu # H (Hermitian): upper triangle of W_Y†W_Y. @inbounds for j in 1:mpert, i in 1:j - wmats_lmda[off + _tri_idx(i, j)] = conj(wy[i]) * wy[j] * scale + wmats_lmda[off+_tri_idx(i, j)] = conj(wy[i]) * wy[j] * scale end off += Mu # B (full): W_Z†W_X. @inbounds for j in 1:mpert, i in 1:mpert - wmats_lmda[off + _full_idx(i, j, mpert)] = conj(wz[i]) * wx[j] * scale + wmats_lmda[off+_full_idx(i, j, mpert)] = conj(wz[i]) * wx[j] * scale end off += mpert^2 # C (full): W_Z†W_Y. @inbounds for j in 1:mpert, i in 1:mpert - wmats_lmda[off + _full_idx(i, j, mpert)] = conj(wz[i]) * wy[j] * scale + wmats_lmda[off+_full_idx(i, j, mpert)] = conj(wz[i]) * wy[j] * scale end off += mpert^2 # E (full): W_X†W_Y. @inbounds for j in 1:mpert, i in 1:mpert - wmats_lmda[off + _full_idx(i, j, mpert)] = conj(wx[i]) * wy[j] * scale + wmats_lmda[off+_full_idx(i, j, mpert)] = conj(wx[i]) * wy[j] * scale end end diff --git a/src/KineticForces/EnergyIntegration.jl b/src/KineticForces/EnergyIntegration.jl index 36cc1ecef..261c403ce 100644 --- a/src/KineticForces/EnergyIntegration.jl +++ b/src/KineticForces/EnergyIntegration.jl @@ -40,10 +40,10 @@ end Collision frequency ν(x) at normalized energy x = E/T. -- `"zero"`: collisionless (ν = 0) -- `"small"`: 1e-5 * we -- `"krook"`: unmodified Krook operator -- `"harmonic"`: (1 + (l/2)²) * krook * x^(-3/2) + - `"zero"`: collisionless (ν = 0) + - `"small"`: 1e-5 * we + - `"krook"`: unmodified Krook operator + - `"harmonic"`: (1 + (l/2)²) * krook * x^(-3/2) """ @inline function _energy_collision_frequency(x::Float64, p::EnergyParams)::Float64 nux = if p.nutype == "zero" @@ -188,7 +188,7 @@ Writing `h(x) = N(x)·exp(-x)`, the limit is `Ω′ = leff·wb/(2√x) + n·wd`, `Ω″ = −leff·wb/(4·x^{3/2})`. """ @inline function _real_pole_regular_part(xr::Float64, p::EnergyParams, leff::Float64, - wb::Float64, n::Int, wd::Float64)::ComplexF64 + wb::Float64, n::Int, wd::Float64)::ComplexF64 sx = sqrt(xr) op = leff * wb / (2.0 * sx) + n * wd # Ω′(x_res) opp = -leff * wb / (4.0 * xr * sx) # Ω″(x_res) @@ -211,8 +211,8 @@ add-back below), and its on-axis `0/0` window by the analytic regular-part limit # Real x-space resonant integrand with pole subtractions # Explicit function keeps memory allocation out of the QuadGK inner loop. @inline function _resonant_integrand(x::Float64, p::EnergyParams, - residues::Vector{ComplexF64}, x_poles::Vector{ComplexF64}, npole::Int, - leff::Float64, wb::Float64, n::Int, wd::Float64)::ComplexF64 + residues::Vector{ComplexF64}, x_poles::Vector{ComplexF64}, npole::Int, + leff::Float64, wb::Float64, n::Int, wd::Float64)::ComplexF64 val = _energy_integrand_real(x, p) @inbounds for k in 1:npole val -= residues[k] / (x - x_poles[k]) @@ -234,8 +234,8 @@ add-back below), and its on-axis `0/0` window by the analytic regular-part limit end function _integrate_energy_resonant(p::EnergyParams, leff::Float64, wb::Float64, - n::Int, we::Float64, wd::Float64, - atol::Float64, rtol::Float64, segbuf=nothing)::ComplexF64 + n::Int, we::Float64, wd::Float64, + atol::Float64, rtol::Float64, segbuf=nothing)::ComplexF64 x_res_list = find_resonance_energies(leff, wb, n, we, wd) # ≤ 2 roots of a quadratic in √x x_poles = ComplexF64[] residues = ComplexF64[] @@ -308,17 +308,18 @@ Distribution function types (`f0type`): `"maxwellian"`, `"jkp"`, `"cgl"`. poles are now handled analytically rather than by contour deformation. # Returns -- `ComplexF64`: energy integral value + + - `ComplexF64`: energy integral value """ function integrate_energy(wn::Float64, wt::Float64, we::Float64, wd::Float64, - wb::Float64, nuk::Float64, ell::Int, leff::Float64, - n::Int, psi::Float64, lambda::Float64, method::String; - nutype::String="harmonic", f0type::String="maxwellian", - nufac::Float64=1.0, ximag::Float64=0.0, qt::Bool=false, - atol::Float64=1e-7, rtol::Float64=1e-5, segbuf=nothing)::ComplexF64 + wb::Float64, nuk::Float64, ell::Int, leff::Float64, + n::Int, psi::Float64, lambda::Float64, method::String; + nutype::String="harmonic", f0type::String="maxwellian", + nufac::Float64=1.0, ximag::Float64=0.0, qt::Bool=false, + atol::Float64=1e-7, rtol::Float64=1e-5, segbuf=nothing)::ComplexF64 p = EnergyParams(wn, wt, we, wd, wb, nuk, leff, n, - nutype, f0type, nufac, ximag, qt) + nutype, f0type, nufac, ximag, qt) # CGL has no resonance denominator and no pole — integrate the physical # x-space integrand directly over the half line (QuadGK maps [0,∞) itself). @@ -343,19 +344,20 @@ N(x)·exp(-x)/denom(x) at specified x = E/T values. Returns the integrand value integrand shape and verifying kinetic resonance resolution. # Example + ```julia -x = 10 .^ range(-2, stop=2, length=500) +x = 10 .^ range(-2; stop=2, length=500) f = KineticForces.evaluate_energy_integrand(x; wn=1e3, wt=2e3, we=5e4, - wd=1e2, wb=3e4, nuk=1e3, leff=1.0, n=1) -plot(x, real.(f); xscale=:log10, xlabel="x = E/T", ylabel="Re(integrand)") + wd=1e2, wb=3e4, nuk=1e3, leff=1.0, n=1) +plot(x, real.(f); xscale=:log10, xlabel=\"x = E/T\", ylabel=\"Re(integrand)\") ``` """ function evaluate_energy_integrand(x_grid::AbstractVector{Float64}; - wn::Float64, wt::Float64, we::Float64, - wd::Float64, wb::Float64, nuk::Float64, - leff::Float64, n::Int, - nutype::String="harmonic", f0type::String="maxwellian", - nufac::Float64=1.0, ximag::Float64=0.0, qt::Bool=false) + wn::Float64, wt::Float64, we::Float64, + wd::Float64, wb::Float64, nuk::Float64, + leff::Float64, n::Int, + nutype::String="harmonic", f0type::String="maxwellian", + nufac::Float64=1.0, ximag::Float64=0.0, qt::Bool=false) p = EnergyParams(wn, wt, we, wd, wb, nuk, leff, n, nutype, f0type, nufac, ximag, qt) return [energy_integrand_scalar(x, p) for x in x_grid] end diff --git a/src/KineticForces/KineticForces.jl b/src/KineticForces/KineticForces.jl index 1ac79ad22..748d19e64 100644 --- a/src/KineticForces/KineticForces.jl +++ b/src/KineticForces/KineticForces.jl @@ -59,11 +59,11 @@ include("CalculatedKineticMatrices.jl") # ============================================================================ const mp = 1.672_614e-27 # proton mass (kg) const me = 9.109_1e-31 # electron mass (kg) -const e = 1.602_191_7e-19 # elementary charge (C) +const e = 1.602_191_7e-19 # elementary charge (C) const eV = e # joules per electron-volt const twopi = 2π -const μ₀ = 4e-7 * π +const μ₀ = 4e-7 * π const rad2deg = 180 / π const deg2rad = π / 180 const iunit = 1im # equivalent to Fortran's (0,1) diff --git a/src/KineticForces/KineticForcesStructs.jl b/src/KineticForces/KineticForcesStructs.jl index e4eca2581..5d2505b69 100644 --- a/src/KineticForces/KineticForcesStructs.jl +++ b/src/KineticForces/KineticForcesStructs.jl @@ -3,12 +3,13 @@ Single source of truth for the NTV calculation methods. Each entry is a NamedTuple `(name, flag, kind, doc)`: -- `name` — short method identifier used as the HDF5 group key and in `intr.method` -- `flag` — the `KineticForcesControl` field symbol that enables the method -- `kind` — dispatch routing tag consumed by `method_kind` / `Torque.jl` - (`:gar` for the GAR/matrix family, `:fcgl`/`:rlar`/`:clar` for the - three special-cased methods) -- `doc` — one-line description printed in verbose output + + - `name` — short method identifier used as the HDF5 group key and in `intr.method` + - `flag` — the `KineticForcesControl` field symbol that enables the method + - `kind` — dispatch routing tag consumed by `method_kind` / `Torque.jl` + (`:gar` for the GAR/matrix family, `:fcgl`/`:rlar`/`:clar` for the + three special-cased methods) + - `doc` — one-line description printed in verbose output The method names/docs and the `Compute.jl` enable list are all derived from this tuple, and `Torque.jl` routes on `kind`, so the methods are enumerated in one place. @@ -77,8 +78,9 @@ User-facing control parameters from the TOML `[KineticForces]` section. Configures which NTV methods to run, species parameters, tolerances, and output options. Constructed via keyword arguments or from a TOML dict: + ```julia -ctrl = KineticForcesControl(; (Symbol(k) => v for (k, v) in inputs["KineticForces"])...) +ctrl = KineticForcesControl(; (Symbol(k) => v for (k, v) in inputs[\"KineticForces\"])...) ``` Immutable: vary a field by building a new control rather than assigning to one (the @@ -202,12 +204,13 @@ Internal working state for KineticForces calculations. Holds equilibrium-derived quantities, profile interpolants, and integration results. Fields replacing former module-level globals: -- `ro`, `bo`, `chi1`: Equilibrium geometry parameters -- `mthsurf`, `mfac`: Poloidal grid info -- `dbob_m`, `divx_m`: Perturbation mode interpolants -- `sing_psis`: Rational-surface ψ locations (sorted, from the stability analysis), used as - panel boundaries for the outer ψ torque quadrature so the resonant peaks fall on - Gauss-Kronrod interval endpoints instead of driving deep adaptive bisection + + - `ro`, `bo`, `chi1`: Equilibrium geometry parameters + - `mthsurf`, `mfac`: Poloidal grid info + - `dbob_m`, `divx_m`: Perturbation mode interpolants + - `sing_psis`: Rational-surface ψ locations (sorted, from the stability analysis), used as + panel boundaries for the outer ψ torque quadrature so the resonant peaks fall on + Gauss-Kronrod interval endpoints instead of driving deep adaptive bisection Equilibrium and kinetic profile data are read directly from the `PlasmaEquilibrium` (`equil.profiles`, `equil.geometry`) and the @@ -297,17 +300,17 @@ function KineticForcesInternal(equil; verbose::Bool=false) # Axis toroidal field F(0)/ro that normalizes λ = μ·bo/E; F_spline stores 2πF. bo_axis = abs(equil.profiles.F_spline(0.0)) / (2π * equil.ro) KineticForcesInternal(; - ro = equil.ro, - bo = bo_axis, - chi1 = 2π * equil.psio, + ro=equil.ro, + bo=bo_axis, + chi1=2π * equil.psio, mthsurf, - tpsi_xs = collect(range(0.0, 1.0, length=nth)), - tpsi_B = Vector{Float64}(undef, nth), - tpsi_dBdpsi = Vector{Float64}(undef, nth), - tpsi_dBdtheta = Vector{Float64}(undef, nth), - tpsi_jac = Vector{Float64}(undef, nth), - tpsi_djdpsi = Vector{Float64}(undef, nth), - verbose, + tpsi_xs=collect(range(0.0, 1.0; length=nth)), + tpsi_B=Vector{Float64}(undef, nth), + tpsi_dBdpsi=Vector{Float64}(undef, nth), + tpsi_dBdtheta=Vector{Float64}(undef, nth), + tpsi_jac=Vector{Float64}(undef, nth), + tpsi_djdpsi=Vector{Float64}(undef, nth), + verbose ) end @@ -317,15 +320,17 @@ end Populate perturbation data from PerturbedEquilibriumState into KineticForcesInternal. Builds three interpolant sets from PE Clebsch displacements: -1. `xs_m` — [ξ^ψ, ∂ξ^ψ/∂ψ, ξ^α] CubicSeriesInterpolants over ψ -2. `dbob_m` — δB/B Fourier modes via JBB deweighting (Fortran set_peq) -3. `divx_m` — ∇·ξ⊥ Fourier modes via JBB deweighting + + 1. `xs_m` — [ξ^ψ, ∂ξ^ψ/∂ψ, ξ^α] CubicSeriesInterpolants over ψ + 2. `dbob_m` — δB/B Fourier modes via JBB deweighting (Fortran set_peq) + 3. `divx_m` — ∇·ξ⊥ Fourier modes via JBB deweighting The JBB deweighting algorithm (Fortran pentrc/inputs.f90:828-868): -1. Apply geometric matrices S,T,X,Y,Z in m-space -2. Inverse DFT to θ-space -3. Divide by J·B² at each θ -4. Forward DFT back to m-space + + 1. Apply geometric matrices S,T,X,Y,Z in m-space + 2. Inverse DFT to θ-space + 3. Divide by J·B² at each θ + 4. Forward DFT back to m-space """ function set_perturbation_data!(kf_intr::KineticForcesInternal, pe_state::PerturbedEquilibrium.PerturbedEquilibriumState, ffs::ForceFreeStates.ForceFreeStatesResult, @@ -399,9 +404,9 @@ function set_perturbation_data!(kf_intr::KineticForcesInternal, pe_state::Pertur psi = psi_grid[ipsi] # Get Clebsch displacement vectors at this ψ - xsp = view(xi_modes.clebsch_psi, ipsi, :) # ξ^ψ [mpert] + xsp = view(xi_modes.clebsch_psi, ipsi, :) # ξ^ψ [mpert] xmp1 = view(xi_modes.clebsch_psi1, ipsi, :) # ∂ξ^ψ/∂ψ [mpert] - xms = view(clebsch_alpha_mat, ipsi, :) # ξ^α [mpert] + xms = view(clebsch_alpha_mat, ipsi, :) # ξ^α [mpert] # Evaluate geometric matrices at ψ → mpert² flat vectors, reshape to mpert×mpert geom_mats.smats(smat_flat, psi; hint=hint_s) @@ -421,8 +426,8 @@ function set_perturbation_data!(kf_intr::KineticForcesInternal, pe_state::Pertur mul!(jbb_kapx, smat, xsp) mul!(jbb_kapx, tmat, xms, 1.0 + 0.0im, 1.0 + 0.0im) # += tmat * xms mul!(jbb_divx, xmat, xmp1) - mul!(jbb_divx, ymat, xsp, 1.0 + 0.0im, 1.0 + 0.0im) # += ymat * xsp - mul!(jbb_divx, zmat, xms, 1.0 + 0.0im, 1.0 + 0.0im) # += zmat * xms + mul!(jbb_divx, ymat, xsp, 1.0 + 0.0im, 1.0 + 0.0im) # += ymat * xsp + mul!(jbb_divx, zmat, xms, 1.0 + 0.0im, 1.0 + 0.0im) # += zmat * xms @. jbb_dbob = -(jbb_divx + jbb_kapx) # Inverse DFT to θ-space, divide by J·B², forward DFT back @@ -449,9 +454,9 @@ Matches Fortran set_peq lines 859-868: transforms JBB-weighted m-space data to θ-space, removes the J·B² weighting at each poloidal angle, and transforms back. """ function _jbb_deweight!(out::AbstractVector{ComplexF64}, jbb_modes::Vector{ComplexF64}, - ft::Utilities.FourierTransforms.FourierTransform, - psi::Float64, equil::Equilibrium.PlasmaEquilibrium, - mthsurf::Int, theta_buf::Vector{ComplexF64}) + ft::Utilities.FourierTransforms.FourierTransform, + psi::Float64, equil::Equilibrium.PlasmaEquilibrium, + mthsurf::Int, theta_buf::Vector{ComplexF64}) # Inverse DFT: m-space → θ-space theta_buf .= Utilities.FourierTransforms.inverse(ft, jbb_modes) @@ -521,8 +526,8 @@ Accumulated results from all KineticForces computations. Written to gpec.h5 under the "KineticForces" group. """ @kwdef mutable struct KineticForcesState - method_results::Dict{String, MethodResult} = Dict{String, MethodResult}() + method_results::Dict{String,MethodResult} = Dict{String,MethodResult}() # Block-diagonal kinetic matrices: key=method, value=(numpert_total, numpert_total, 6) - kinetic_matrices::Dict{String, Array{ComplexF64,3}} = Dict{String, Array{ComplexF64,3}}() + kinetic_matrices::Dict{String,Array{ComplexF64,3}} = Dict{String,Array{ComplexF64,3}}() completed::Bool = false end diff --git a/src/KineticForces/Output.jl b/src/KineticForces/Output.jl index 75f527ae2..96594f06d 100644 --- a/src/KineticForces/Output.jl +++ b/src/KineticForces/Output.jl @@ -140,8 +140,9 @@ Write variable-length integration trajectory records using offset-indexed concat This is the standard HDF5 ragged array pattern for storing variable-length data. # Arguments -- `mg::HDF5.Group`: HDF5 group for this method -- `records::Vector{EnergyIntegrationResult}`: Integration records to write + + - `mg::HDF5.Group`: HDF5 group for this method + - `records::Vector{EnergyIntegrationResult}`: Integration records to write """ function write_integration_records!(mg::HDF5.Group, records::Vector{EnergyIntegrationResult}) rg = create_group(mg, "EnergyIntegrals") @@ -173,13 +174,14 @@ end Print a summary of KineticForces results to stdout. # Arguments -- `state::KineticForcesState`: Accumulated computation results -- `verbose::Bool`: Print detailed per-surface results + + - `state::KineticForcesState`: Accumulated computation results + - `verbose::Bool`: Print detailed per-surface results """ function print_summary(state::KineticForcesState; verbose::Bool=false) for (method_name, result) in state.method_results @printf("%-8s T_phi = %11.3e 2n*dW_k = %11.3e\n", - method_name, real(result.total_torque), imag(result.total_torque)) + method_name, real(result.total_torque), imag(result.total_torque)) end if verbose for (method_name, _) in state.kinetic_matrices diff --git a/src/KineticForces/PitchIntegration.jl b/src/KineticForces/PitchIntegration.jl index 845cfabc9..52fd40ec6 100644 --- a/src/KineticForces/PitchIntegration.jl +++ b/src/KineticForces/PitchIntegration.jl @@ -61,15 +61,17 @@ Gauss-Kronrod quadrature. Uses `QuadGK.quadgk!` with an in-place ComplexF64 kernel buffer. The fbnce interpolant returns [ωb, ωd, f₁, f₂, ...] at each λ, where: -- f₁ = ωb|δJ|²/ro² (scalar torque) -- f₂:end = ωb·W_outer_products/ro² (kinetic matrix elements, if present) + + - f₁ = ωb|δJ|²/ro² (scalar torque) + - f₂:end = ωb·W_outer_products/ro² (kinetic matrix elements, if present) Splits the domain at the trapped/passing boundary so Gauss-Kronrod resolves the kink in leff = ell + n*q (circulating) → ell (trapped). One `quadgk!` call writes all `nqty` complex quantities per λ-evaluation. # Returns -- `Vector{ComplexF64}` of length nqty: integrated pitch-angle results + + - `Vector{ComplexF64}` of length nqty: integrated pitch-angle results """ function integrate_pitch_gar_quadgk( wn::Float64, wt::Float64, we::Float64, nuk::Float64, @@ -129,28 +131,28 @@ function _pitch_gar_kernel_quadgk!(out::Vector{ComplexF64}, lambda, p::PitchGARP if is_circulating xint_co = integrate_energy(p.wn, p.wt, p.we, wd, wb, nueff, - p.ell, leff, p.n, p.psi, lambda, p.method; - nutype=p.nutype, f0type=p.f0type, - nufac=p.nufac, ximag=p.ximag, qt=p.qt, - atol=p.energy_atol, rtol=p.energy_rtol, segbuf=p.esegbuf) + p.ell, leff, p.n, p.psi, lambda, p.method; + nutype=p.nutype, f0type=p.f0type, + nufac=p.nufac, ximag=p.ximag, qt=p.qt, + atol=p.energy_atol, rtol=p.energy_rtol, segbuf=p.esegbuf) xint_counter = integrate_energy(p.wn, p.wt, p.we, wd, -wb, nueff, - p.ell, leff, p.n, p.psi, lambda, p.method; - nutype=p.nutype, f0type=p.f0type, - nufac=p.nufac, ximag=p.ximag, qt=p.qt, - atol=p.energy_atol, rtol=p.energy_rtol, segbuf=p.esegbuf) + p.ell, leff, p.n, p.psi, lambda, p.method; + nutype=p.nutype, f0type=p.f0type, + nufac=p.nufac, ximag=p.ximag, qt=p.qt, + atol=p.energy_atol, rtol=p.energy_rtol, segbuf=p.esegbuf) xint = xint_co + xint_counter else xint = integrate_energy(p.wn, p.wt, p.we, wd, wb, nueff, - p.ell, leff, p.n, p.psi, lambda, p.method; - nutype=p.nutype, f0type=p.f0type, - nufac=p.nufac, ximag=p.ximag, qt=p.qt, - atol=p.energy_atol, rtol=p.energy_rtol) + p.ell, leff, p.n, p.psi, lambda, p.method; + nutype=p.nutype, f0type=p.f0type, + nufac=p.nufac, ximag=p.ximag, qt=p.qt, + atol=p.energy_atol, rtol=p.energy_rtol) end xint_decomposed = complex(p.rex * real(xint), p.imx * imag(xint)) @inbounds for i in 1:p.nqty - out[i] = fvals[i + 2] * xint_decomposed + out[i] = fvals[i+2] * xint_decomposed end return nothing end @@ -212,8 +214,8 @@ end _pitch_gar_kernel_quadgk_wt!(out::Vector{ComplexF64}, lambda, p::PitchGARParams) Dual-output pitch kernel. Fills a length-`2*nqty` buffer: - out[1:nqty] — fwmm half: `fvals * complex(0, imag(xint))` - out[nqty+1:2*nqty] — ftmm half: `fvals * complex(real(xint), 0)` +out[1:nqty] — fwmm half: `fvals * complex(0, imag(xint))` +out[nqty+1:2*nqty] — ftmm half: `fvals * complex(real(xint), 0)` One energy integration per λ; both halves share it. """ @@ -229,22 +231,22 @@ function _pitch_gar_kernel_quadgk_wt!(out::Vector{ComplexF64}, lambda, p::PitchG if is_circulating xint_co = integrate_energy(p.wn, p.wt, p.we, wd, wb, nueff, - p.ell, leff, p.n, p.psi, lambda, p.method; - nutype=p.nutype, f0type=p.f0type, - nufac=p.nufac, ximag=p.ximag, qt=p.qt, - atol=p.energy_atol, rtol=p.energy_rtol, segbuf=p.esegbuf) + p.ell, leff, p.n, p.psi, lambda, p.method; + nutype=p.nutype, f0type=p.f0type, + nufac=p.nufac, ximag=p.ximag, qt=p.qt, + atol=p.energy_atol, rtol=p.energy_rtol, segbuf=p.esegbuf) xint_counter = integrate_energy(p.wn, p.wt, p.we, wd, -wb, nueff, - p.ell, leff, p.n, p.psi, lambda, p.method; - nutype=p.nutype, f0type=p.f0type, - nufac=p.nufac, ximag=p.ximag, qt=p.qt, - atol=p.energy_atol, rtol=p.energy_rtol, segbuf=p.esegbuf) + p.ell, leff, p.n, p.psi, lambda, p.method; + nutype=p.nutype, f0type=p.f0type, + nufac=p.nufac, ximag=p.ximag, qt=p.qt, + atol=p.energy_atol, rtol=p.energy_rtol, segbuf=p.esegbuf) xint = xint_co + xint_counter else xint = integrate_energy(p.wn, p.wt, p.we, wd, wb, nueff, - p.ell, leff, p.n, p.psi, lambda, p.method; - nutype=p.nutype, f0type=p.f0type, - nufac=p.nufac, ximag=p.ximag, qt=p.qt, - atol=p.energy_atol, rtol=p.energy_rtol) + p.ell, leff, p.n, p.psi, lambda, p.method; + nutype=p.nutype, f0type=p.f0type, + nufac=p.nufac, ximag=p.ximag, qt=p.qt, + atol=p.energy_atol, rtol=p.energy_rtol) end xint_w = complex(0.0, imag(xint)) # fwmm: rex=0, imx=1 @@ -252,9 +254,9 @@ function _pitch_gar_kernel_quadgk_wt!(out::Vector{ComplexF64}, lambda, p::PitchG nq = p.nqty @inbounds for i in 1:nq - f = fvals[i + 2] - out[i] = f * xint_w - out[i + nq] = f * xint_t + f = fvals[i+2] + out[i] = f * xint_w + out[i+nq] = f * xint_t end return nothing end diff --git a/src/KineticForces/Torque.jl b/src/KineticForces/Torque.jl index 1cd40285e..99949647c 100644 --- a/src/KineticForces/Torque.jl +++ b/src/KineticForces/Torque.jl @@ -6,36 +6,39 @@ Toroidal torque resulting from nonambipolar transport in perturbed equilibrium. Imaginary component is proportional to the kinetic energy Im(T) = 2*n*dW_k. # Arguments -- `tpsi_var`: Output complex torque value -- `psi::Float64`: Normalized poloidal flux -- `n::Int`: Toroidal mode number -- `l::Int`: Bounce harmonic number -- `zi::Int`: Ion charge in fundamental units (e) -- `mi::Int`: Ion mass (units of proton mass) -- `wdfac::Float64`: Drift factor -- `divxfac::Float64`: Divergence factor -- `electron::Bool`: Calculate quantities for electrons (zi,mi ignored) -- `method::String`: Integration method (RLAR, CLAR, *GAR, *TMM, *WMM, *KMM) + + - `tpsi_var`: Output complex torque value + - `psi::Float64`: Normalized poloidal flux + - `n::Int`: Toroidal mode number + - `l::Int`: Bounce harmonic number + - `zi::Int`: Ion charge in fundamental units (e) + - `mi::Int`: Ion mass (units of proton mass) + - `wdfac::Float64`: Drift factor + - `divxfac::Float64`: Divergence factor + - `electron::Bool`: Calculate quantities for electrons (zi,mi ignored) + - `method::String`: Integration method (RLAR, CLAR, *GAR, *TMM, *WMM, *KMM) where * = F,T,P for full,trapped,passing -- `equil`: PlasmaEquilibrium with 2D interpolants and named profile/geometry splines -- `intr::KineticForcesInternal`: Internal state with mode indexing and perturbation splines -- `kinetic_profiles::Equilibrium.KineticProfileSplines`: Named kinetic-profile splines + - `equil`: PlasmaEquilibrium with 2D interpolants and named profile/geometry splines + - `intr::KineticForcesInternal`: Internal state with mode indexing and perturbation splines + - `kinetic_profiles::Equilibrium.KineticProfileSplines`: Named kinetic-profile splines (n_i, n_e, T_i, T_e, ω_E, ν_i, ν_e) loaded from `kinetic.dat` # Optional Arguments -- `op_wmats::Array{ComplexF64,3}`: Store ForceFreeStates matrix elements + + - `op_wmats::Array{ComplexF64,3}`: Store ForceFreeStates matrix elements # Returns -- `ComplexF64`: Toroidal torque due to nonambipolar transport + + - `ComplexF64`: Toroidal torque due to nonambipolar transport """ function tpsi!(tpsi_var::Ref{ComplexF64}, psi::Float64, n::Int, l::Int, - zi::Int, mi::Int, wdfac::Float64, divxfac::Float64, - electron::Bool, method::String, equil, intr::KineticForcesInternal, - kinetic_profiles::Equilibrium.KineticProfileSplines; - op_wmats::Union{Nothing,Array{ComplexF64,3}}=nothing, - rex_override::Union{Nothing,Float64}=nothing, - imx_override::Union{Nothing,Float64}=nothing, - atol_xlmda::Float64=1e-9, rtol_xlmda::Float64=1e-6) + zi::Int, mi::Int, wdfac::Float64, divxfac::Float64, + electron::Bool, method::String, equil, intr::KineticForcesInternal, + kinetic_profiles::Equilibrium.KineticProfileSplines; + op_wmats::Union{Nothing,Array{ComplexF64,3}}=nothing, + rex_override::Union{Nothing,Float64}=nothing, + imx_override::Union{Nothing,Float64}=nothing, + atol_xlmda::Float64=1e-9, rtol_xlmda::Float64=1e-6) # Enforce bounds if psi > 1 @@ -72,12 +75,12 @@ function tpsi!(tpsi_var::Ref{ComplexF64}, psi::Float64, n::Int, l::Int, # Sample poloidal quantities on theta grid (buffers pre-allocated on intr). mthsurf_local = intr.mthsurf - xs = intr.tpsi_xs - B_vals = intr.tpsi_B - dBdpsi_vals = intr.tpsi_dBdpsi + xs = intr.tpsi_xs + B_vals = intr.tpsi_B + dBdpsi_vals = intr.tpsi_dBdpsi dBdtheta_vals = intr.tpsi_dBdtheta - jac_vals = intr.tpsi_jac - djdpsi_vals = intr.tpsi_djdpsi + jac_vals = intr.tpsi_jac + djdpsi_vals = intr.tpsi_djdpsi hB = intr.hint2d_eqfun_B hJ = intr.hint2d_rzphi_jac @@ -144,14 +147,14 @@ function tpsi!(tpsi_var::Ref{ComplexF64}, psi::Float64, n::Int, l::Int, # Flux-function quantities — read directly from named splines on the # PlasmaEquilibrium and the externally-loaded KineticProfileSplines. - q = equil.profiles.q_spline(psi) - dVdpsi = equil.profiles.dVdpsi_spline(psi) + q = equil.profiles.q_spline(psi) + dVdpsi = equil.profiles.dVdpsi_spline(psi) if electron - n_s = kinetic_profiles.ne_spline(psi) - T_s = kinetic_profiles.Te_spline(psi) + n_s = kinetic_profiles.ne_spline(psi) + T_s = kinetic_profiles.Te_spline(psi) dn_s_dpsi = kinetic_profiles.ne_deriv(psi) dT_s_dpsi = kinetic_profiles.Te_deriv(psi) - nu_s = kinetic_profiles.nue_spline(psi) + nu_s = kinetic_profiles.nue_spline(psi) else # ni_spline / nui_spline carry THIS species' resonant density and its # full-composition collisionality (per-species views built by the loader). @@ -159,7 +162,7 @@ function tpsi!(tpsi_var::Ref{ComplexF64}, psi::Float64, n::Int, l::Int, T_s = kinetic_profiles.Ti_spline(psi) dn_s_dpsi = kinetic_profiles.ni_deriv(psi) dT_s_dpsi = kinetic_profiles.Ti_deriv(psi) - nu_s = kinetic_profiles.nui_spline(psi) + nu_s = kinetic_profiles.nui_spline(psi) end welec = kinetic_profiles.omegaE_spline(psi) @@ -167,10 +170,10 @@ function tpsi!(tpsi_var::Ref{ComplexF64}, psi::Float64, n::Int, l::Int, # time from the kinetic-profile derivatives — no longer baked into the loader. wdian = -twopi * T_s * dn_s_dpsi / (chrg * intr.chi1 * n_s) wdiat = -twopi * dT_s_dpsi / (chrg * intr.chi1) - wphi = welec + wdian + wdiat + wphi = welec + wdian + wdiat wtran = sqrt(2 * T_s / mass) / (q * intr.ro) wgyro = chrg * intr.bo / mass - nuk = nu_s + nuk = nu_s rsquared_bmin = equil.rzphi_rsquared((psi, theta_bmin)) if rsquared_bmin <= 0 @@ -187,7 +190,7 @@ function tpsi!(tpsi_var::Ref{ComplexF64}, psi::Float64, n::Int, l::Int, avg_r = equil.geometry.avg_r_spline(psi) avg_R = equil.geometry.avg_R_spline(psi) - epsr = avg_r / avg_R + epsr = avg_r / avg_R wbhat = (π / 4) * sqrt(epsr / 2) * wtran wdhat = q^3 * wtran^2 / (4 * epsr * wgyro) * wdfac nueff = nu_s / (2 * epsr) @@ -196,17 +199,17 @@ function tpsi!(tpsi_var::Ref{ComplexF64}, psi::Float64, n::Int, l::Int, kind = method_kind(method) if kind == :fcgl tpsi_var[] = calculate_fcgl(psi, n, l, tspl, dbob_m_f, divx_m_f, divxfac, - n_s, T_s, equil, intr) + n_s, T_s, equil, intr) elseif kind == :rlar tpsi_var[] = calculate_rlar(psi, n, l, q, epsr, wdian, wdiat, welec, - wdhat, wbhat, nueff, dVdpsi, n_s, T_s, - dbob_m_f, intr.bo, bmin) + wdhat, wbhat, nueff, dVdpsi, n_s, T_s, + dbob_m_f, intr.bo, bmin) elseif kind == :clar tpsi_var[] = calculate_clar(psi, n, l, q, epsr, wdian, wdiat, welec, - nuk, intr.bo, bmax, bmin, n_s, T_s, mass, chrg, - tspl, dbob_m_f, divx_m_f, divxfac, wdfac) + nuk, intr.bo, bmax, bmin, n_s, T_s, mass, chrg, + tspl, dbob_m_f, divx_m_f, divxfac, wdfac) else # :gar — fgar/tgar/pgar + all *mm matrix methods # Evaluate geometric matrices at current ψ if matrix path @@ -223,17 +226,17 @@ function tpsi!(tpsi_var::Ref{ComplexF64}, psi::Float64, n::Int, l::Int, zmat_f = reshape(intr.zmats(psi), intr.mpert, intr.mpert) end tpsi_var[] = calculate_gar(psi, n, l, q, epsr, wdian, wdiat, welec, - nuk, intr.bo, bmax, bmin, n_s, T_s, mass, chrg, - tspl, dbob_m_f, divx_m_f, divxfac, wdfac, - method, op_wmats; - chi1=intr.chi1, ro=intr.ro, mfac=intr.mfac, - mpert=intr.mpert, theta_bmax=theta_bmax, - B_extrap=B_extrap, - smat=smat_f, tmat=tmat_f, xmat=xmat_f, - ymat=ymat_f, zmat=zmat_f, - energy_atol=atol_xlmda, energy_rtol=rtol_xlmda, - pitch_atol=atol_xlmda, pitch_rtol=rtol_xlmda, - rex_override=rex_override, imx_override=imx_override) + nuk, intr.bo, bmax, bmin, n_s, T_s, mass, chrg, + tspl, dbob_m_f, divx_m_f, divxfac, wdfac, + method, op_wmats; + chi1=intr.chi1, ro=intr.ro, mfac=intr.mfac, + mpert=intr.mpert, theta_bmax=theta_bmax, + B_extrap=B_extrap, + smat=smat_f, tmat=tmat_f, xmat=xmat_f, + ymat=ymat_f, zmat=zmat_f, + energy_atol=atol_xlmda, energy_rtol=rtol_xlmda, + pitch_atol=atol_xlmda, pitch_rtol=rtol_xlmda, + rex_override=rex_override, imx_override=imx_override) end return nothing @@ -255,8 +258,8 @@ Only valid for bounce harmonic l=0. Based on: [Logan et al., Phys. Plasmas 2013] """ function calculate_fcgl(psi, n, l, tspl, dbob_m_f, divx_m_f, divxfac::Float64, - n_s::Float64, T_s::Float64, equil, - intr::KineticForcesInternal)::ComplexF64 + n_s::Float64, T_s::Float64, equil, + intr::KineticForcesInternal)::ComplexF64 # Only implemented for l=0 if l != 0 @@ -267,7 +270,7 @@ function calculate_fcgl(psi, n, l, tspl, dbob_m_f, divx_m_f, divxfac::Float64, # Create spline for poloidal integrands cglspl = zeros(2, mthsurf_local + 1) - theta_vals = range(0, 1, length=mthsurf_local + 1) + theta_vals = range(0, 1; length=mthsurf_local + 1) # Evaluate poloidal functions and field perturbations hB = intr.hint2d_eqfun_B @@ -301,8 +304,8 @@ function calculate_fcgl(psi, n, l, tspl, dbob_m_f, divx_m_f, divxfac::Float64, # Calculate torque: T = 2*n*i*n_s*T_s * [weighted integral] result = 2.0 * n * im * n_s * T_s * - (0.5 * (5.0/3.0) * integral_1 + - 0.5 * (1.0/3.0) * integral_2) + (0.5 * (5.0/3.0) * integral_1 + + 0.5 * (1.0/3.0) * integral_2) return result end @@ -319,9 +322,9 @@ Valid for low aspect ratio tokamaks (ε << 1). Reference: [Logan et al., Phys. Plasmas, 2013] """ function calculate_rlar(psi, n, l, q, epsr, wdian, wdiat, welec, - wdhat, wbhat, nueff, dVdpsi::Float64, - n_s::Float64, T_s::Float64, - dbob_m_f, bo, bmin=0.5)::ComplexF64 + wdhat, wbhat, nueff, dVdpsi::Float64, + n_s::Float64, T_s::Float64, + dbob_m_f, bo, bmin=0.5)::ComplexF64 # Setup parameters for energy integration lnq = Float64(l) # Resonant mode for trapped particles @@ -332,11 +335,11 @@ function calculate_rlar(psi, n, l, q, epsr, wdian, wdiat, welec, # Energy-space quadrature # This computes ∫ K(x) dx where K is the resonance operator xint = integrate_energy(wdian, wdiat, welec, wdhat, wbhat, nueff, - l, lnq, n, psi, lmdamax, "rlar") + l, lnq, n, psi, lmdamax, "rlar") # Kappa/bounce averaging (effect of field perturbations) # Placeholder: simplified estimate - kappaint_val = sqrt(mean(abs.(dbob_m_f).^2)) + kappaint_val = sqrt(mean(abs.(dbob_m_f) .^ 2)) # dV/dpsi gradient term from Clebsch coordinate Jacobian psi_factor = dVdpsi @@ -363,8 +366,8 @@ Includes bounce-averaged integrals over lambda (pitch angle). Status: Partially implemented (stub for full calculation) """ function calculate_clar(psi, n, l, q, epsr, wdian, wdiat, welec, nuk, bo, - bmax, bmin, n_s::Float64, T_s::Float64, mass, chrg, tspl, - dbob_m_f, divx_m_f, divxfac, wdfac)::ComplexF64 + bmax, bmin, n_s::Float64, T_s::Float64, mass, chrg, tspl, + dbob_m_f, divx_m_f, divxfac, wdfac)::ComplexF64 @warn "CLAR method not yet fully implemented, returning zero" maxlog=1 return ComplexF64(0.0, 0.0) @@ -384,35 +387,37 @@ Can compute torque (*TMM), energy (*WMM), or matrix elements (*KMM/*RMM). Ports Fortran torque.F90 GAR branch (lines 529-932). # Steps -1. Compute bounce-averaged quantities via `compute_bounce_data()` -2. Build fbnce interpolant over λ, normalize for numerical stability -3. Integrate over pitch angle via `integrate_pitch_gar_quadgk()` -4. Apply torque normalization (Eq. 19, Logan et al. 2013) -5. If matrix path: assemble and normalize kinetic matrices + + 1. Compute bounce-averaged quantities via `compute_bounce_data()` + 2. Build fbnce interpolant over λ, normalize for numerical stability + 3. Integrate over pitch angle via `integrate_pitch_gar_quadgk()` + 4. Apply torque normalization (Eq. 19, Logan et al. 2013) + 5. If matrix path: assemble and normalize kinetic matrices # Keyword Arguments (rex/imx override) -- `rex_override::Union{Nothing,Float64}`: Override real-part multiplier for resonance - operator. When both overrides are provided, bypasses method-string derivation. -- `imx_override::Union{Nothing,Float64}`: Override imaginary-part multiplier. - Use `rex_override=1.0, imx_override=1.0` to get full complex result for - simultaneous kwmat/ktmat extraction via `compute_kinetic_matrices_at_psi!`. + + - `rex_override::Union{Nothing,Float64}`: Override real-part multiplier for resonance + operator. When both overrides are provided, bypasses method-string derivation. + - `imx_override::Union{Nothing,Float64}`: Override imaginary-part multiplier. + Use `rex_override=1.0, imx_override=1.0` to get full complex result for + simultaneous kwmat/ktmat extraction via `compute_kinetic_matrices_at_psi!`. Reference: [Logan et al., Phys. Plasmas 20, 122507 (2013)] """ function calculate_gar(psi, n, l, q, epsr, wdian, wdiat, welec, nuk, bo, - bmax, bmin, n_s::Float64, T_s::Float64, mass, chrg, tspl, - dbob_m_f, divx_m_f, divxfac, wdfac, method, op_wmats; - chi1::Float64, ro::Float64, mfac::Vector{Int}, mpert::Int, - theta_bmax::Float64, B_extrap, - smat=nothing, tmat=nothing, xmat=nothing, - ymat=nothing, zmat=nothing, - nlmda::Int=128, ntheta::Int=128, - nutype::String="harmonic", f0type::String="maxwellian", - nufac::Float64=1.0, ximag::Float64=0.0, qt::Bool=false, - energy_atol::Float64=1e-7, energy_rtol::Float64=1e-5, - pitch_atol::Float64=1e-9, pitch_rtol::Float64=1e-6, - rex_override::Union{Nothing,Float64}=nothing, - imx_override::Union{Nothing,Float64}=nothing)::ComplexF64 + bmax, bmin, n_s::Float64, T_s::Float64, mass, chrg, tspl, + dbob_m_f, divx_m_f, divxfac, wdfac, method, op_wmats; + chi1::Float64, ro::Float64, mfac::Vector{Int}, mpert::Int, + theta_bmax::Float64, B_extrap, + smat=nothing, tmat=nothing, xmat=nothing, + ymat=nothing, zmat=nothing, + nlmda::Int=128, ntheta::Int=128, + nutype::String="harmonic", f0type::String="maxwellian", + nufac::Float64=1.0, ximag::Float64=0.0, qt::Bool=false, + energy_atol::Float64=1e-7, energy_rtol::Float64=1e-5, + pitch_atol::Float64=1e-9, pitch_rtol::Float64=1e-6, + rex_override::Union{Nothing,Float64}=nothing, + imx_override::Union{Nothing,Float64}=nothing)::ComplexF64 # Bounce-averaged quantities per pitch angle bounce = compute_bounce_data( @@ -443,7 +448,7 @@ function calculate_gar(psi, n, l, q, epsr, wdian, wdiat, welec, nuk, bo, # keeps the historical OLD-path behavior (torque pipeline uses only the # real part of the outer products). @inbounds for q in 1:nqty_mat, ilmda in 1:bounce.nlmda - fbnce_data[ilmda, 3 + q] = real(bounce.wmats_vs_lambda[ilmda, q]) + fbnce_data[ilmda, 3+q] = real(bounce.wmats_vs_lambda[ilmda, q]) end end @@ -497,7 +502,7 @@ function calculate_gar(psi, n, l, q, epsr, wdian, wdiat, welec, nuk, bo, base = 1 # lxint offset after scalar-torque slot (index 1) # Helper: fetch normalized pitch integral at lxint[base+q] for q ∈ [1..nqty_mat]. - @inline elem(q) = complex(lxint[base + q] / fbnce_norm[base + q]) * energy_factor + @inline elem(q) = complex(lxint[base+q] / fbnce_norm[base+q]) * energy_factor # A (Hermitian, k=1): upper triangle stored at q ∈ [1..Mu]; mirror to lower. off = 0 @@ -586,7 +591,7 @@ without perturbing the perturbative torque pipeline. function _setup_surface_state( psi::Float64, zi::Int, mi::Int, electron::Bool, equil, intr::KineticForcesInternal, - kinetic_profiles::Equilibrium.KineticProfileSplines, + kinetic_profiles::Equilibrium.KineticProfileSplines ) if electron chrg = -1 * e @@ -597,12 +602,12 @@ function _setup_surface_state( end mthsurf_local = intr.mthsurf - xs = intr.tpsi_xs - B_vals = intr.tpsi_B - dBdpsi_vals = intr.tpsi_dBdpsi + xs = intr.tpsi_xs + B_vals = intr.tpsi_B + dBdpsi_vals = intr.tpsi_dBdpsi dBdtheta_vals = intr.tpsi_dBdtheta - jac_vals = intr.tpsi_jac - djdpsi_vals = intr.tpsi_djdpsi + jac_vals = intr.tpsi_jac + djdpsi_vals = intr.tpsi_djdpsi hB = intr.hint2d_eqfun_B hJ = intr.hint2d_rzphi_jac @@ -657,17 +662,17 @@ function _setup_surface_state( q = equil.profiles.q_spline(psi) if electron - n_s = kinetic_profiles.ne_spline(psi) - T_s = kinetic_profiles.Te_spline(psi) + n_s = kinetic_profiles.ne_spline(psi) + T_s = kinetic_profiles.Te_spline(psi) dn_s_dpsi = kinetic_profiles.ne_deriv(psi) dT_s_dpsi = kinetic_profiles.Te_deriv(psi) - nu_s = kinetic_profiles.nue_spline(psi) + nu_s = kinetic_profiles.nue_spline(psi) else - n_s = kinetic_profiles.ni_spline(psi) - T_s = kinetic_profiles.Ti_spline(psi) + n_s = kinetic_profiles.ni_spline(psi) + T_s = kinetic_profiles.Ti_spline(psi) dn_s_dpsi = kinetic_profiles.ni_deriv(psi) dT_s_dpsi = kinetic_profiles.Ti_deriv(psi) - nu_s = kinetic_profiles.nui_spline(psi) + nu_s = kinetic_profiles.nui_spline(psi) end welec = kinetic_profiles.omegaE_spline(psi) @@ -675,7 +680,7 @@ function _setup_surface_state( wdiat = -twopi * dT_s_dpsi / (chrg * intr.chi1) wtran = sqrt(2 * T_s / mass) / (q * intr.ro) wgyro = chrg * intr.bo / mass - nuk = nu_s + nuk = nu_s rsquared_bmin = equil.rzphi_rsquared((psi, theta_bmin)) rsquared_bmin > 0 || @@ -683,14 +688,14 @@ function _setup_surface_state( avg_r = equil.geometry.avg_r_spline(psi) avg_R = equil.geometry.avg_R_spline(psi) - epsr = avg_r / avg_R + epsr = avg_r / avg_R return (; chrg, mass, tspl, B_extrap, bmax, bmin, theta_bmax, q, n_s, T_s, welec, wdian, wdiat, wtran, wgyro, nuk, - epsr, + epsr ) end @@ -714,8 +719,8 @@ match against Fortran `fourfit.F:1080-1082` (`kwmat_l`, `ktmat_l`). For the Hermitian-outer-product blocks A/D/H stored as upper-triangles, the mirror rule differs between halves: - kwmat[j,i] = conj(kwmat[i,j]) — Hermitian (S_w pure imaginary) - ktmat[j,i] = -conj(ktmat[i,j]) — anti-Hermitian (S_t pure real) +kwmat[j,i] = conj(kwmat[i,j]) — Hermitian (S_w pure imaginary) +ktmat[j,i] = -conj(ktmat[i,j]) — anti-Hermitian (S_t pure real) Derivation: `conj(S_w) = -S_w` vs `conj(S_t) = S_t`, combined with `conj(factor) = -factor` (factor = -i/(2n)). These mirrors recover Fortran's independent-slot computation at the mirrored (j,i) positions. @@ -735,8 +740,8 @@ function kinetic_energy_matrices_for_euler_lagrange!( mpert = intr.mpert mfac = intr.mfac chi1 = intr.chi1 - ro = intr.ro - bo = intr.bo + ro = intr.ro + bo = intr.bo # Geometric matrices at this ψ smat_f = reshape(intr.smats(psi), mpert, mpert) @@ -805,7 +810,7 @@ function kinetic_energy_matrices_for_euler_lagrange!( Mu = (mpert * (mpert + 1)) ÷ 2 # Fetch normalized element at pitch-integral slot q, from either half. # half_offset = 0 for wmm (→kwmat), = nqty for tmm (→ktmat). - @inline elem(q, half_offset) = complex(lxint[half_offset + q] / fbnce_norm[q]) * energy_factor + @inline elem(q, half_offset) = complex(lxint[half_offset+q] / fbnce_norm[q]) * energy_factor # For A/D/H Hermitian-outer-product blocks stored as upper-triangles, the # lower-triangle reconstruction uses different mirrors per half: @@ -829,11 +834,16 @@ function kinetic_energy_matrices_for_euler_lagrange!( for (dest, half, mirror_sign) in ((kwmat, 0, 1.0), (ktmat, nqty, -1.0)) off = 0 - _assemble_hermitian!(dest, 1, off, half, mirror_sign); off += Mu # A (k=1) - _assemble_hermitian!(dest, 4, off, half, mirror_sign); off += Mu # D (k=4) - _assemble_hermitian!(dest, 6, off, half, mirror_sign); off += Mu # H (k=6) - _assemble_full!(dest, 2, off, half); off += mpert^2 # B (k=2) - _assemble_full!(dest, 3, off, half); off += mpert^2 # C (k=3) + _assemble_hermitian!(dest, 1, off, half, mirror_sign) + off += Mu # A (k=1) + _assemble_hermitian!(dest, 4, off, half, mirror_sign) + off += Mu # D (k=4) + _assemble_hermitian!(dest, 6, off, half, mirror_sign) + off += Mu # H (k=6) + _assemble_full!(dest, 2, off, half) + off += mpert^2 # B (k=2) + _assemble_full!(dest, 3, off, half) + off += mpert^2 # C (k=3) _assemble_full!(dest, 5, off, half) # E (k=5) end @@ -875,14 +885,15 @@ adjoint combinations `kwmat ± ktmat` in `ForceFreeStates/Kinetic.jl` / Fortran `dcon/sing.f:967-1075` for non-Hermitian B_k, C_k, E_k. # Arguments -- `kwmat::Array{ComplexF64,3}`: Output (mpert×mpert×6), fwmm half, zeroed on entry -- `ktmat::Array{ComplexF64,3}`: Output (mpert×mpert×6), ftmm half, zeroed on entry -- `psi, n, l, zi, mi, wdfac, divxfac, electron`: Same as `tpsi!` (divxfac unused - on the matrix path — retained for call-site compatibility) -- `equil`: PlasmaEquilibrium -- `intr::KineticForcesInternal`: Internal state with mode indexing, geometric - matrices (smats/tmats/xmats/ymats/zmats), and per-surface θ-grid buffers -- `kinetic_profiles::Equilibrium.KineticProfileSplines`: Named kinetic-profile splines + + - `kwmat::Array{ComplexF64,3}`: Output (mpert×mpert×6), fwmm half, zeroed on entry + - `ktmat::Array{ComplexF64,3}`: Output (mpert×mpert×6), ftmm half, zeroed on entry + - `psi, n, l, zi, mi, wdfac, divxfac, electron`: Same as `tpsi!` (divxfac unused + on the matrix path — retained for call-site compatibility) + - `equil`: PlasmaEquilibrium + - `intr::KineticForcesInternal`: Internal state with mode indexing, geometric + matrices (smats/tmats/xmats/ymats/zmats), and per-surface θ-grid buffers + - `kinetic_profiles::Equilibrium.KineticProfileSplines`: Named kinetic-profile splines Reference: [Logan et al., Phys. Plasmas 20, 122507 (2013)] """ @@ -904,7 +915,7 @@ function compute_kinetic_matrices_at_psi!( end state = _setup_surface_state(psi, zi, mi, electron, - equil, intr, kinetic_profiles) + equil, intr, kinetic_profiles) kinetic_energy_matrices_for_euler_lagrange!( kwmat, ktmat, state, psi, n, l, wdfac, intr; @@ -914,5 +925,3 @@ function compute_kinetic_matrices_at_psi!( return nothing end - - diff --git a/src/KineticForces/Utils.jl b/src/KineticForces/Utils.jl index 51c0cd3a8..0be9b3406 100644 --- a/src/KineticForces/Utils.jl +++ b/src/KineticForces/Utils.jl @@ -44,7 +44,7 @@ in `psi_panel_points`). function _resonance_nodes_from_frequencies(wbhat_f, welec_f, wdhat_f, grid; n::Int, nl::Int, xeval::Float64=2.5) nodes = Float64[] sx = sqrt(xeval) - for l in -nl:nl + for l in (-nl):nl append!(nodes, find_sign_change_roots(psi -> l * wbhat_f(psi) * sx + n * (welec_f(psi) + wdhat_f(psi) * xeval), grid)) end return nodes @@ -71,7 +71,7 @@ the estimate degenerates. Panel placement only needs ~peak-width accuracy, so th estimates (single spline evaluations) are sufficient and no bounce averaging is performed. """ function kinetic_resonance_psi_nodes(kinetic_profiles::Equilibrium.KineticProfileSplines, equil; - n::Int, nl::Int, zi::Int=1, mi::Int=2, electron::Bool=false, wdfac::Float64=1.0, xeval::Float64=2.5) + n::Int, nl::Int, zi::Int=1, mi::Int=2, electron::Bool=false, wdfac::Float64=1.0, xeval::Float64=2.5) chrg = electron ? -e : zi * e mass = electron ? me : mi * mp T_spline = electron ? kinetic_profiles.Te_spline : kinetic_profiles.Ti_spline diff --git a/src/LocalStability/Ballooning.jl b/src/LocalStability/Ballooning.jl index 2add47a62..5f11e9992 100644 --- a/src/LocalStability/Ballooning.jl +++ b/src/LocalStability/Ballooning.jl @@ -755,17 +755,18 @@ function ballooning_alpha_crossings( # Δ' as a function of the α scaling at fixed magnetic shear. Failed evaluations # (extreme corrections can break the coefficient assembly) count as non-stable # samples and are rejected by the crossing classification, like in scan_delta_prime_map. - delta_at(scale) = try - ballooning_delta_prime( - psi_idx, - plasma_eq; - corr_qprime=0.0, - corr_pprime=ref.pprime_norm_ref * (scale - 1.0), - theta_k=theta_k - ).delta_prime - catch - NaN - end + delta_at(scale) = + try + ballooning_delta_prime( + psi_idx, + plasma_eq; + corr_qprime=0.0, + corr_pprime=ref.pprime_norm_ref * (scale - 1.0), + theta_k=theta_k + ).delta_prime + catch + NaN + end samples = collect(range(0.0, max_alpha_scale; length=n_scan + 1)) scales = _ballooning_marginal_crossings(delta_at, samples, tol; max_crossings=max_crossings) @@ -796,7 +797,7 @@ function _ballooning_marginal_crossings(delta_at, samples, tol; pole_cap=3.0, ma k0 == 0 && return Float64[] d_anchor = abs(d_prev) locs = Float64[] - for k in k0+1:n + for k in (k0+1):n d = delta_at(samples[k]) if isfinite(d_prev) && isfinite(d) && sign(d) != sign(d_prev) && max(abs(d_prev), abs(d)) <= pole_cap * d_anchor lo, hi = samples[k-1], samples[k] @@ -981,17 +982,18 @@ function ballooning_qprime_crossings( # Δ' as a function of the q' scaling at the experimental pressure gradient. Failed # evaluations (reversed-shear corrections can break the coefficient assembly) count # as non-stable samples and are rejected by the crossing classification. - delta_at(scale) = try - ballooning_delta_prime( - psi_idx, - plasma_eq; - corr_qprime=ref.qprime_norm_ref * (scale - 1.0), - corr_pprime=0.0, - theta_k=theta_k - ).delta_prime - catch - NaN - end + delta_at(scale) = + try + ballooning_delta_prime( + psi_idx, + plasma_eq; + corr_qprime=ref.qprime_norm_ref * (scale - 1.0), + corr_pprime=0.0, + theta_k=theta_k + ).delta_prime + catch + NaN + end samples = collect(range(max_qprime_scale, min_qprime_scale; length=n_scan + 1)) scales = _ballooning_marginal_crossings(delta_at, samples, tol) diff --git a/src/PerturbedEquilibrium/FieldReconstruction.jl b/src/PerturbedEquilibrium/FieldReconstruction.jl index 65f36ee51..f4532c6ef 100644 --- a/src/PerturbedEquilibrium/FieldReconstruction.jl +++ b/src/PerturbedEquilibrium/FieldReconstruction.jl @@ -980,10 +980,12 @@ function _apply_rzphi_transform( # Per-thread scratch (the immutable `ft` functor and `geom` are shared read-only): θ-space # transform inputs/outputs (length mtheta) and mode-space forward-DFT outputs (length mpert), # so the DFTs run in place with no per-surface allocation. - bufs = [(R=zeros(ComplexF64, mtheta), Z=zeros(ComplexF64, mtheta), P=zeros(ComplexF64, mtheta), - psi=zeros(ComplexF64, mtheta), th=zeros(ComplexF64, mtheta), ze=zeros(ComplexF64, mtheta), - Ro=zeros(ComplexF64, mpert), Zo=zeros(ComplexF64, mpert), Po=zeros(ComplexF64, mpert)) - for _ in 1:Threads.maxthreadid()] + bufs = [ + (R=zeros(ComplexF64, mtheta), Z=zeros(ComplexF64, mtheta), P=zeros(ComplexF64, mtheta), + psi=zeros(ComplexF64, mtheta), th=zeros(ComplexF64, mtheta), ze=zeros(ComplexF64, mtheta), + Ro=zeros(ComplexF64, mpert), Zo=zeros(ComplexF64, mpert), Po=zeros(ComplexF64, mpert)) + for _ in 1:Threads.maxthreadid() + ] Threads.@threads :static for ipsi in 1:npsi buf = bufs[Threads.threadid()] diff --git a/src/PerturbedEquilibrium/PerturbedEquilibriumStructs.jl b/src/PerturbedEquilibrium/PerturbedEquilibriumStructs.jl index d8251de38..aa1250030 100644 --- a/src/PerturbedEquilibrium/PerturbedEquilibriumStructs.jl +++ b/src/PerturbedEquilibrium/PerturbedEquilibriumStructs.jl @@ -26,7 +26,9 @@ Medium Priority (defer for MWE): - `singular_point_method::String` - Method for singular point treatment (default: "standard") Regularization: - # High Priority (MWE) + +# High Priority (MWE) + - `reg_spot::Float64` - Regularization width for singular surface smoothing (default: 0.05). Set to 0 to disable. Must be ≥ 0. """ @kwdef struct PerturbedEquilibriumControl @@ -121,6 +123,7 @@ Metadata [n_rational] — identifies each (surface, n) row: Control-surface forcing/response spectra [numpert_total], in the three Pharr (2026) field representations (all tesla; no flux/weber is stored): + - `forcing_b`/`response_b` - bare normal field b (Σ⁻¹·b̃) - `forcing_b_rootarea`/`response_b_rootarea` - root-area-weighted field b̃ (coordinate-invariant) - `forcing_b_area`/`response_b_area` - area-weighted field b̄ (= S·b̃; flux is Φ = A·b̄) @@ -185,18 +188,18 @@ well-conditioned flux-space inductances L, Λ: rational_surface_idx::Vector{Int} = Int[] # Control-surface forcing/response spectra in the three weightings of field representations [numpert_total], tesla - forcing_b::Vector{ComplexF64} = ComplexF64[] # bare normal field b (forcing Φ_x) - forcing_b_rootarea::Vector{ComplexF64} = ComplexF64[] # root-area-weighted field b̃ (coordinate-invariant) - forcing_b_area::Vector{ComplexF64} = ComplexF64[] # area-weighted field b̄ - response_b::Vector{ComplexF64} = ComplexF64[] # bare normal field b (response Φ_tot = P·Φ_x) + forcing_b::Vector{ComplexF64} = ComplexF64[] # bare normal field b (forcing Φ_x) + forcing_b_rootarea::Vector{ComplexF64} = ComplexF64[] # root-area-weighted field b̃ (coordinate-invariant) + forcing_b_area::Vector{ComplexF64} = ComplexF64[] # area-weighted field b̄ + response_b::Vector{ComplexF64} = ComplexF64[] # bare normal field b (response Φ_tot = P·Φ_x) response_b_rootarea::Vector{ComplexF64} = ComplexF64[] # root-area-weighted field b̃ - response_b_area::Vector{ComplexF64} = ComplexF64[] # area-weighted field b̄ + response_b_area::Vector{ComplexF64} = ComplexF64[] # area-weighted field b̄ # Control surface matrices [numpert_total × numpert_total], root-area-weighted field (b̃) space - plasma_inductance::Matrix{ComplexF64} = zeros(ComplexF64, 0, 0) # Λ̃ (field space) + plasma_inductance::Matrix{ComplexF64} = zeros(ComplexF64, 0, 0) # Λ̃ (field space) surface_inductance::Matrix{ComplexF64} = zeros(ComplexF64, 0, 0) # L̃ (field space) - permeability::Matrix{ComplexF64} = zeros(ComplexF64, 0, 0) # P̃ = R⁻¹·Λ·L⁻¹·R - reluctance::Matrix{ComplexF64} = zeros(ComplexF64, 0, 0) # ϱ̃ = R†·L⁻¹·(Λ−L)·L⁻¹·R + permeability::Matrix{ComplexF64} = zeros(ComplexF64, 0, 0) # P̃ = R⁻¹·Λ·L⁻¹·R + reluctance::Matrix{ComplexF64} = zeros(ComplexF64, 0, 0) # ϱ̃ = R†·L⁻¹·(Λ−L)·L⁻¹·R rootarea_to_area_weight::Matrix{ComplexF64} = zeros(ComplexF64, 0, 0) # S = Σ/√A at psilim: b̃→b̄ recovery operator surface_area::Float64 = 0.0 # scalar control-surface area A = ∫J|∇ψ|dθ (flux: Φ = A·b̄; conform R = S·A) diff --git a/src/PerturbedEquilibrium/Utils.jl b/src/PerturbedEquilibrium/Utils.jl index fc1eb9c0a..38be26f87 100644 --- a/src/PerturbedEquilibrium/Utils.jl +++ b/src/PerturbedEquilibrium/Utils.jl @@ -12,8 +12,9 @@ avoiding repeated index arithmetic throughout the code. ## Mode Indexing Convention For linear index i ∈ [1, numpert_total]: -- m_modes[i] = (i-1) % mpert + mlow -- n_modes[i] = (i-1) ÷ mpert + nlow + + - m_modes[i] = (i-1) % mpert + mlow + - n_modes[i] = (i-1) ÷ mpert + nlow This matches the convention used in ForceFreeStates where modes are ordered as: (m1,n1), (m2,n1), ..., (mpert,n1), (m1,n2), (m2,n2), ..., (mpert,npert) @@ -110,47 +111,47 @@ function write_outputs_to_HDF5( # Forcing modes forcing_group = haskey(pe_group, "ForcingModes") ? pe_group["ForcingModes"] : create_group(pe_group, "ForcingModes") - forcing_group["n"] = [mode.n for mode in intr.forcing_modes] - forcing_group["m"] = [mode.m for mode in intr.forcing_modes] + forcing_group["n"] = [mode.n for mode in intr.forcing_modes] + forcing_group["m"] = [mode.m for mode in intr.forcing_modes] forcing_group["amplitude"] = [mode.amplitude for mode in intr.forcing_modes] # Control-surface forcing/response spectra in the three Pharr field representations # (all tesla; flux/weber is never stored). b̃ = root-area-weighted (coordinate-invariant). - !isempty(state.forcing_b) && (pe_group["forcing_b"] = state.forcing_b) - !isempty(state.forcing_b_rootarea) && (pe_group["forcing_b_root_area"] = state.forcing_b_rootarea) - !isempty(state.forcing_b_area) && (pe_group["forcing_b_area"] = state.forcing_b_area) - !isempty(state.response_b) && (pe_group["response_b"] = state.response_b) + !isempty(state.forcing_b) && (pe_group["forcing_b"] = state.forcing_b) + !isempty(state.forcing_b_rootarea) && (pe_group["forcing_b_root_area"] = state.forcing_b_rootarea) + !isempty(state.forcing_b_area) && (pe_group["forcing_b_area"] = state.forcing_b_area) + !isempty(state.response_b) && (pe_group["response_b"] = state.response_b) !isempty(state.response_b_rootarea) && (pe_group["response_b_root_area"] = state.response_b_rootarea) - !isempty(state.response_b_area) && (pe_group["response_b_area"] = state.response_b_area) + !isempty(state.response_b_area) && (pe_group["response_b_area"] = state.response_b_area) # Control surface matrices [numpert_total × numpert_total], in coordinate-invariant # root-area-weighted field (b̃) space. Recover the area-weighted field b̄ with the stored # operator S ≡ rootarea_to_area_weight (b̄ = S·b̃): e.g. L_b̄ = S·L̃·S†; recover flux with the # scalar surface_area A: Φ = A·b̄ (internally R = S·A, Φ = R·b̃). [Pharr 2026] mat_group = haskey(pe_group, "ResponseMatrices") ? pe_group["ResponseMatrices"] : create_group(pe_group, "ResponseMatrices") - !isempty(state.plasma_inductance) && (mat_group["plasma_inductance"] = state.plasma_inductance) + !isempty(state.plasma_inductance) && (mat_group["plasma_inductance"] = state.plasma_inductance) !isempty(state.surface_inductance) && (mat_group["surface_inductance"] = state.surface_inductance) - !isempty(state.permeability) && (mat_group["permeability"] = state.permeability) - !isempty(state.reluctance) && (mat_group["reluctance"] = state.reluctance) + !isempty(state.permeability) && (mat_group["permeability"] = state.permeability) + !isempty(state.reluctance) && (mat_group["reluctance"] = state.reluctance) !isempty(state.rootarea_to_area_weight) && (mat_group["rootarea_to_area_weight_operator"] = state.rootarea_to_area_weight) - (state.surface_area != 0.0) && (mat_group["surface_area"] = state.surface_area) + (state.surface_area != 0.0) && (mat_group["surface_area"] = state.surface_area) # Response fields (ComplexF64 directly) response_group = haskey(pe_group, "Response") ? pe_group["Response"] : create_group(pe_group, "Response") !isempty(state.psi_grid) && (response_group["psi"] = state.psi_grid) have_xi = !isnothing(state.xi_modes) - have_b = have_xi && !isnothing(state.b_modes) - response_group["xi_psi"] = have_xi ? state.xi_modes.psi : ComplexF64[] - response_group["b_psi_area_weighted"] = have_b ? state.b_modes.b_psi_area_weighted : ComplexF64[] - response_group["Jb_theta"] = have_b ? state.b_modes.theta : ComplexF64[] - response_group["Jb_zeta"] = have_b ? state.b_modes.zeta : ComplexF64[] - response_group["b_n"] = !isnothing(state.b_n_modes) ? state.b_n_modes : ComplexF64[] - response_group["xi_n"] = !isnothing(state.xi_n_modes) ? state.xi_n_modes : ComplexF64[] + have_b = have_xi && !isnothing(state.b_modes) + response_group["xi_psi"] = have_xi ? state.xi_modes.psi : ComplexF64[] + response_group["b_psi_area_weighted"] = have_b ? state.b_modes.b_psi_area_weighted : ComplexF64[] + response_group["Jb_theta"] = have_b ? state.b_modes.theta : ComplexF64[] + response_group["Jb_zeta"] = have_b ? state.b_modes.zeta : ComplexF64[] + response_group["b_n"] = !isnothing(state.b_n_modes) ? state.b_n_modes : ComplexF64[] + response_group["xi_n"] = !isnothing(state.xi_n_modes) ? state.xi_n_modes : ComplexF64[] # Clebsch displacements for PENTRC (matches Fortran gpout_xclebsch) if have_xi - response_group["xi_clebsch_psi"] = state.xi_modes.clebsch_psi - response_group["dxi_clebsch_psidpsi"] = state.xi_modes.clebsch_psi1 + response_group["xi_clebsch_psi"] = state.xi_modes.clebsch_psi + response_group["dxi_clebsch_psidpsi"] = state.xi_modes.clebsch_psi1 response_group["xi_clebsch_alpha"] = state.xi_modes.clebsch_alpha end @@ -158,36 +159,36 @@ function write_outputs_to_HDF5( if have_xi response_group["Jxi_psi"] = state.xi_modes.psi_J response_group["Jxi_theta"] = state.xi_modes.theta - response_group["Jxi_zeta"] = state.xi_modes.zeta + response_group["Jxi_zeta"] = state.xi_modes.zeta end # Covariant components (from gpeq_cova) if have_xi - response_group["xi_cov_psi"] = state.xi_modes.cova_psi + response_group["xi_cov_psi"] = state.xi_modes.cova_psi response_group["xi_cov_theta"] = state.xi_modes.cova_theta - response_group["xi_cov_zeta"] = state.xi_modes.cova_zeta + response_group["xi_cov_zeta"] = state.xi_modes.cova_zeta end if have_xi response_group["Jxi_theta_reg"] = state.xi_modes.theta_reg - response_group["Jxi_zeta_reg"] = state.xi_modes.zeta_reg + response_group["Jxi_zeta_reg"] = state.xi_modes.zeta_reg end if have_b response_group["Jb_theta_reg"] = state.b_modes.theta_reg - response_group["Jb_zeta_reg"] = state.b_modes.zeta_reg - response_group["b_cov_psi"] = state.b_modes.cova_psi + response_group["Jb_zeta_reg"] = state.b_modes.zeta_reg + response_group["b_cov_psi"] = state.b_modes.cova_psi response_group["b_cov_theta"] = state.b_modes.cova_theta - response_group["b_cov_zeta"] = state.b_modes.cova_zeta + response_group["b_cov_zeta"] = state.b_modes.cova_zeta end # R,Z,φ cylindrical components in mode-space (from gpeq_rzphi) if have_xi - response_group["xi_R"] = state.xi_modes.R - response_group["xi_Z"] = state.xi_modes.Z + response_group["xi_R"] = state.xi_modes.R + response_group["xi_Z"] = state.xi_modes.Z response_group["xi_phi"] = state.xi_modes.phi end if have_b - response_group["b_R"] = state.b_modes.R - response_group["b_Z"] = state.b_modes.Z + response_group["b_R"] = state.b_modes.R + response_group["b_Z"] = state.b_modes.Z response_group["b_phi"] = state.b_modes.phi end @@ -195,34 +196,34 @@ function write_outputs_to_HDF5( coupling_group = haskey(pe_group, "SingularCoupling") ? pe_group["SingularCoupling"] : create_group(pe_group, "SingularCoupling") # Coupling matrices [n_rational × numpert_total] - !isempty(state.C_resonant_area_weighted_field) && (coupling_group["C_resonant_area_weighted_field"] = state.C_resonant_area_weighted_field) + !isempty(state.C_resonant_area_weighted_field) && (coupling_group["C_resonant_area_weighted_field"] = state.C_resonant_area_weighted_field) !isempty(state.C_resonant_current) && (coupling_group["C_resonant_current"] = state.C_resonant_current) - !isempty(state.C_island_width_sq) && (coupling_group["C_island_width_sq"] = state.C_island_width_sq) + !isempty(state.C_island_width_sq) && (coupling_group["C_island_width_sq"] = state.C_island_width_sq) !isempty(state.C_penetrated_area_weighted_field) && (coupling_group["C_penetrated_area_weighted_field"] = state.C_penetrated_area_weighted_field) - !isempty(state.C_delta_prime) && (coupling_group["C_Delta_prime"] = state.C_delta_prime) + !isempty(state.C_delta_prime) && (coupling_group["C_Delta_prime"] = state.C_delta_prime) # Applied resonant vectors [n_rational] - !isempty(state.resonant_area_weighted_field) && (coupling_group["resonant_area_weighted_field"] = state.resonant_area_weighted_field) - !isempty(state.resonant_current) && (coupling_group["resonant_current"] = state.resonant_current) - !isempty(state.island_width_sq) && (coupling_group["island_width_sq"] = state.island_width_sq) - !isempty(state.penetrated_area_weighted_field) && (coupling_group["penetrated_area_weighted_field"] = state.penetrated_area_weighted_field) - !isempty(state.delta_prime) && (coupling_group["Delta_prime"] = state.delta_prime) - !isempty(state.forcing_solution_weights) && (coupling_group["forcing_solution_weights"] = state.forcing_solution_weights) + !isempty(state.resonant_area_weighted_field) && (coupling_group["resonant_area_weighted_field"] = state.resonant_area_weighted_field) + !isempty(state.resonant_current) && (coupling_group["resonant_current"] = state.resonant_current) + !isempty(state.island_width_sq) && (coupling_group["island_width_sq"] = state.island_width_sq) + !isempty(state.penetrated_area_weighted_field) && (coupling_group["penetrated_area_weighted_field"] = state.penetrated_area_weighted_field) + !isempty(state.delta_prime) && (coupling_group["Delta_prime"] = state.delta_prime) + !isempty(state.forcing_solution_weights) && (coupling_group["forcing_solution_weights"] = state.forcing_solution_weights) !isempty(state.rational_area) && (coupling_group["rational_area"] = state.rational_area) - !isempty(state.island_half_width) && (coupling_group["island_half_width"] = state.island_half_width) + !isempty(state.island_half_width) && (coupling_group["island_half_width"] = state.island_half_width) !isempty(state.chirikov_parameter) && (coupling_group["chirikov_parameter"] = state.chirikov_parameter) # Metadata [n_rational] - !isempty(state.rational_psi) && (coupling_group["rational_psi"] = state.rational_psi) - !isempty(state.rational_q) && (coupling_group["rational_q"] = state.rational_q) - !isempty(state.rational_m_res) && (coupling_group["rational_m"] = state.rational_m_res) - !isempty(state.rational_n) && (coupling_group["rational_n"] = state.rational_n) + !isempty(state.rational_psi) && (coupling_group["rational_psi"] = state.rational_psi) + !isempty(state.rational_q) && (coupling_group["rational_q"] = state.rational_q) + !isempty(state.rational_m_res) && (coupling_group["rational_m"] = state.rational_m_res) + !isempty(state.rational_n) && (coupling_group["rational_n"] = state.rational_n) # Energies energy_group = haskey(pe_group, "Energies") ? pe_group["Energies"] : create_group(pe_group, "Energies") - energy_group["vacuum_energy"] = state.vacuum_energy - energy_group["surface_energy"] = state.surface_energy - energy_group["plasma_energy"] = state.plasma_energy + energy_group["vacuum_energy"] = state.vacuum_energy + energy_group["surface_energy"] = state.surface_energy + energy_group["plasma_energy"] = state.plasma_energy energy_group["toroidal_torque"] = state.toroidal_torque annotate_pe!(pe_group) @@ -261,7 +262,8 @@ const PE_H5_ANNOTATIONS = [ "Response/xi_cov_psi" => (; long_name="covariant radial displacement ξ_ψ = ξ·e_ψ", units="m^2", dims=("psi", "mode"), attach=(1 => "Response/psi",)), "Response/xi_cov_theta" => (; long_name="covariant poloidal displacement ξ_θ = ξ·e_θ", units="m^2", dims=("psi", "mode"), attach=(1 => "Response/psi",)), "Response/xi_cov_zeta" => (; long_name="covariant toroidal displacement ξ_ζ = ξ·e_ζ", units="m^2", dims=("psi", "mode"), attach=(1 => "Response/psi",)), - "Response/xi_clebsch_psi" => (; long_name="Clebsch displacement component ξ^ψ (PENTRC input, gpout_xclebsch convention)", dims=("psi", "mode"), attach=(1 => "Response/psi",)), + "Response/xi_clebsch_psi" => + (; long_name="Clebsch displacement component ξ^ψ (PENTRC input, gpout_xclebsch convention)", dims=("psi", "mode"), attach=(1 => "Response/psi",)), "Response/dxi_clebsch_psidpsi" => (; long_name="regularized ψ_N derivative of ξ^ψ (× singfac²/(singfac²+reg_spot²))", dims=("psi", "mode"), attach=(1 => "Response/psi",)), "Response/xi_clebsch_alpha" => diff --git a/src/Rerun.jl b/src/Rerun.jl index 03c19bea6..a71401637 100644 --- a/src/Rerun.jl +++ b/src/Rerun.jl @@ -37,7 +37,8 @@ function read_equilibrium_ingest(in_h5) haskey(in_h5, group_path) || return nothing group = in_h5[group_path] kind = read(group, "ingest_kind") - T = kind == "direct" ? Equilibrium.DirectIngest : + T = + kind == "direct" ? Equilibrium.DirectIngest : kind == "inverse" ? Equilibrium.InverseIngest : error("Unknown equilibrium ingest_kind in gpec.h5: $kind (expected \"direct\" or \"inverse\")") # Positional reconstruction: relies on the default constructor, so `fieldnames(T)` order @@ -75,8 +76,8 @@ numbers, booleans, and quoted strings without worrying about shell quoting. function parse_override_flag(expr::AbstractString) eqidx = findfirst(==('='), expr) eqidx === nothing && error("--override expects key=value, got: $expr") - lhs = String(strip(expr[1:eqidx-1])) - rhs = String(strip(expr[eqidx+1:end])) + lhs = String(strip(expr[1:(eqidx-1)])) + rhs = String(strip(expr[(eqidx+1):end])) isempty(lhs) && error("--override key cannot be empty: $expr") parts = split(lhs, '.') @@ -97,7 +98,7 @@ function parse_override_flag(expr::AbstractString) # Build nested dict from dotted path. root = Dict{String,Any}() cursor = root - for p in parts[1:end-1] + for p in parts[1:(end-1)] cursor[String(p)] = Dict{String,Any}() cursor = cursor[String(p)] end @@ -176,7 +177,7 @@ function resolve_rerun_output_path(source_h5::String, output_dir::String, output source_abs = abspath(source_h5) if output_name === nothing base = basename(source_abs) - stem = endswith(lowercase(base), ".h5") ? base[1:end-3] : base + stem = endswith(lowercase(base), ".h5") ? base[1:(end-3)] : base output_name = string(stem, "_rerun.h5") end if abspath(joinpath(output_dir, output_name)) == source_abs @@ -281,9 +282,11 @@ function build_inputs_from_h5(args::Vector{String}) elseif ingest isa Equilibrium.InverseIngest Equilibrium.build_inverse_from_ingest(eq_config, ingest) else - error("gpec.h5 has no equilibrium ingest and eq_type=$(eq_config.eq_type) is not analytic — cannot replay. " * - "A file-based eq_type needs a stored ingest (pre-ingest snapshots lack one); a new analytic kind must be " * - "registered in Equilibrium.ANALYTIC_EQ.") + error( + "gpec.h5 has no equilibrium ingest and eq_type=$(eq_config.eq_type) is not analytic — cannot replay. " * + "A file-based eq_type needs a stored ingest (pre-ingest snapshots lack one); a new analytic kind must be " * + "registered in Equilibrium.ANALYTIC_EQ." + ) end return inputs, eq_config, additional_input, output_dir, current_git, preloaded_forcing, preloaded_coils diff --git a/src/Tearing/CriticalResonantField/CriticalResonantField.jl b/src/Tearing/CriticalResonantField/CriticalResonantField.jl index 453f04b73..1fe90461a 100644 --- a/src/Tearing/CriticalResonantField/CriticalResonantField.jl +++ b/src/Tearing/CriticalResonantField/CriticalResonantField.jl @@ -14,8 +14,8 @@ using ..InnerLayer using ..InnerLayer: InnerLayerModel, solve_inner, GGJModel, GGJParameters, SLAYERModel, SLAYERParameters -#include("TorqueBalance.jl") +include("TorqueBalance.jl") -#export TorqueBalance, torque_balance +export TorqueBalance, torque_balance_value, torque_balance_scan end # module CriticalResonantField diff --git a/src/Tearing/CriticalResonantField/TorqueBalance.jl b/src/Tearing/CriticalResonantField/TorqueBalance.jl index c85bff102..517737c57 100644 --- a/src/Tearing/CriticalResonantField/TorqueBalance.jl +++ b/src/Tearing/CriticalResonantField/TorqueBalance.jl @@ -25,98 +25,62 @@ """ TorqueBalance{M<:InnerLayerModel, P} -Per-surface dispersion data: `(model, params, dp_diag, dc, scale, tauk)`. -Calling `sc(Q)` returns the complex residual +Per-surface torque balance data: `(model, params, Q0, P, lu, sval)`. -``` -r(Q) = dp_diag - scale * solve_inner(model, params, Q).tearing - dc -``` - -A root of `sc` in the complex `Q` plane is a **tearing** eigenvalue at -this surface in the *uncoupled* approximation (only the tearing channel -of the inner-layer response appears — the interchange channel enters the -full 2m×2m dispersion via `MultiSurfaceCoupling`, not this scalar form). -Coupled multi-surface eigenvalues come from `MultiSurfaceCoupling` -evaluating the determinant of the modified Δ' matrix. """ -struct SurfaceCoupling{M<:InnerLayerModel,P} + +struct TorqueBalance{M<:InnerLayerModel,P} model::M params::P - dp_diag::ComplexF64 - dc::Float64 - scale::Float64 - tauk::Float64 + Q0::Float64 + P::Float64 + lu::Float64 + sval::Float64 end -function (sc::SurfaceCoupling)(Q::Number) - Δ = solve_inner(sc.model, sc.params, ComplexF64(Q)).tearing - return sc.dp_diag - sc.scale * Δ - sc.dc +function torque_balance_value(tb::TorqueBalance, Q::Number) + Δ = solve_inner(tb.model, tb.params, ComplexF64(Q)).tearing + delta_n_p = 1e-2 # JK hack to avoid singularity at Δ=0.0. Need to fix this in the future. + jxb = -imag(1.0 / (Δ + delta_n_p)) + return 2.0 * tb.P * (tb.Q0 - Q) / jxb, Δ end """ - surface_coupling(model::SLAYERModel, params::SLAYERParameters, - dp_diag::Number; dc::Real=0.0) -> SurfaceCoupling + torque_balance_scan(model::InnerLayerModel, params::InnerLayerParameters, Q0::Real, P::Real, + lu::Real, sval::Real;Qmin=-10.0, Qmax=10.0, n=200) -> (Qs, bal, Qs_positive, bal_positive, + Qpeak, br_crit, Qpeak_ind, Δs) -SLAYER convenience constructor. `scale` is set to `params.lu^(1/3)` so that -the dimensionless Δ from `riccati_f` is mapped to outer ψ-units before -subtraction from the Δ' diagonal. `tauk` is taken from `params.tauk` for use -by `MultiSurfaceCoupling` Q rescaling. +Scan over a range of Q values to find the maximum of the torque balance equation. +Returns the Q values, torque balance values, positive Q values, positive torque balance values, +the Q value at the peak, the critical resonant field, the index of the peak Q value, and the Δ values for each Q. """ -function surface_coupling(model::SLAYERModel, params::SLAYERParameters, - dp_diag::Number; dc::Real=0.0) - return SurfaceCoupling(model, params, ComplexF64(dp_diag), - Float64(dc), params.lu^(1 / 3), params.tauk) -end -""" - surface_coupling(model::GGJModel, params::GGJParameters, - dp_diag::Number) -> SurfaceCoupling +function torque_balance_scan(tb; Qmin=-10.0, Qmax=10.0, n=200) + Qs = range(Qmin, Qmax; length=n) + torque_out = [torque_balance_value(tb, q) for q in Qs] + bal = [x[1] for x in torque_out] + Δs = [x[2] for x in torque_out] + positive = isfinite.(bal) .& (bal .> 0.0) -GGJ convenience constructor. `scale` is `1.0` because GGJ's `solve_inner` -applies its own `rescale_delta` (S^(2p₁/3)·v1^(2p₁)) internally, so the -returned Δ is already in outer units. `tauk` defaults to `1.0` (GGJ has no -direct analogue of SLAYER's per-surface time normalization, so multi-surface -Q rescaling is a no-op for GGJ surfaces unless overridden). + if !any(positive) + return Qs, bal, [0.0], [0.0], 0.0, 0.0, NaN, Δs + end + i = argmax(bal) + Qpeak_ind = i + Qpeak = Qs[i] + maxbal = bal[i] -**No `dc` kwarg**: GGJ's 4m×4m Pletzer-Dewar residual already includes the -interchange channel, which provides Glasser (Mercier) stabilization -natively. A Δ_crit proxy (χ_parallel-matching offset on the diagonal) is -meaningful only for tearing-only slab-layer approximations like SLAYER; -for GGJ it would double-count the interchange physics. The `SurfaceCoupling` -struct's `dc` field is hard-wired to 0 here. -""" -function surface_coupling(model::GGJModel, params::GGJParameters, - dp_diag::Number) - return SurfaceCoupling(model, params, ComplexF64(dp_diag), - 0.0, 1.0, 1.0) -end + Qs_positive = Qs[positive] + bal_positive = bal[positive] -""" - surface_coupling(model::InnerLayerModel, params, dp_diag::Number; - dc::Real=0.0, scale::Real=1.0, tauk::Real=1.0) - -> SurfaceCoupling - -Generic fallback constructor. Use this when wiring a new inner-layer model -into the dispersion solver — pass the appropriate inner→outer-units `scale` -and per-surface `tauk` explicitly. -""" -function surface_coupling(model::InnerLayerModel, params, dp_diag::Number; - dc::Real=0.0, scale::Real=1.0, tauk::Real=1.0) - return SurfaceCoupling(model, params, ComplexF64(dp_diag), - Float64(dc), Float64(scale), Float64(tauk)) -end + i = argmax(bal_positive) + #Qpeak = Qs_positive[i] -function torque_balance_value(tb::TorqueBalance, Q::Number) - Δ = solve_inner(tb.model, tb.params, ComplexF64(Q)).tearing - jxb = -imag(1.0 / (Δ + tb.delta_n_p)) - return 2.0 * tb.P * (tb.Q0 - Q) / jxb -end + #maxbal = bal_positive[i] -function scan_torque_balance(tb; Qmin=-10.0, Qmax=10.0, nscan=200) - qs = range(Qmin, Qmax; length=nscan) - vals = torque_balance_value.(Ref(tb), qs) - idx = argmax(vals) - return qs[idx], vals[idx] + br_crit = sqrt(maxbal / tb.lu * (tb.sval^2 / 2.0)) + return Qs, bal, Qs_positive, bal_positive, Qpeak, br_crit, Qpeak_ind, Δs end -br_th = sqrt(maxbal / tb.lu * (tb.sval^2 / 2.0)) +# Need to fix and improve this function. The positive masking is not helpful. +# Need to avoid poles from Q_e and Q_i. diff --git a/src/Tearing/CriticalResonantField/bcrit_dev.ipynb b/src/Tearing/CriticalResonantField/bcrit_dev.ipynb index 78490c308..4af00e1f0 100644 --- a/src/Tearing/CriticalResonantField/bcrit_dev.ipynb +++ b/src/Tearing/CriticalResonantField/bcrit_dev.ipynb @@ -23,16 +23,11 @@ "using GeneralizedPerturbedEquilibrium: Analysis\n", "using GeneralizedPerturbedEquilibrium: InnerLayer\n", "using GeneralizedPerturbedEquilibrium.InnerLayer: solve_inner\n", - "using GeneralizedPerturbedEquilibrium: Tearing\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2", - "metadata": {}, - "outputs": [], - "source": [ + "using GeneralizedPerturbedEquilibrium: Tearing\n", + "using ..InnerLayer\n", + "using ..InnerLayer: InnerLayerModel, solve_inner, GGJModel, GGJParameters,\n", + " SLAYERModel, SLAYERParameters\n", + "\n", "using Plots\n", "default(\n", " fontfamily=\"Georgia\",\n", @@ -45,23 +40,23 @@ { "cell_type": "code", "execution_count": null, - "id": "3", + "id": "2", "metadata": {}, "outputs": [], "source": [ - "struct TorqueBalance\n", - " model\n", - " params\n", + "struct TorqueBalance{M<:InnerLayerModel,P}\n", + " model::M\n", + " params::P\n", " Q0::Float64\n", " P::Float64\n", - " delta_n_p::Float64\n", " lu::Float64\n", " sval::Float64\n", "end\n", "\n", "function torque_balance_value(tb::TorqueBalance, Q::Number)\n", " Δ = solve_inner(tb.model, tb.params, ComplexF64(Q)).tearing\n", - " jxb = -imag(1.0 / (Δ + tb.delta_n_p))\n", + " delta_n_p = 1e-2\n", + " jxb = -imag(1.0 / (Δ + delta_n_p))\n", " return 2.0 * tb.P * (tb.Q0 - Q) / jxb, Δ\n", "end\n", "\n", @@ -94,108 +89,162 @@ { "cell_type": "code", "execution_count": null, - "id": "4", + "id": "3", "metadata": {}, "outputs": [], "source": [ - "function torque_balance_scan(tb; Qmin=-10.0, Qmax=10.0, n=200)\n", - " Qs = range(Qmin, Qmax; length=n)\n", - " torque_out = [torque_balance_value(tb, q) for q in Qs]\n", - " bal = [x[1] for x in torque_out]\n", - " Δs = [x[2] for x in torque_out]\n", + "# You can substitute any valid SLAYERParameters you already have.\n", + "# This is just an example skeleton.\n", + "p = GeneralizedPerturbedEquilibrium.InnerLayer.slayer_parameters(\n", + " n_e=1e19, t_e=1e3, t_i=1e3,\n", + " omega=0.0, omega_e=4, omega_i=-2,\n", + " qval=2.0, sval_r=0.5, bt=2.0, rs=1.0, R0=3.0, mu_i=2.0, zeff=1.0,\n", + " chi_perp=1.0, chi_tor=1.0, m=2, n=1\n", + ")\n", + "p2 = GeneralizedPerturbedEquilibrium.InnerLayer.SLAYERParameters(\n", + " ising=p.ising,\n", + " m=p.m, n=p.n,\n", + " tau=p.tau, lu=p.lu, c_beta=p.c_beta, D_norm=p.D_norm,\n", + " P_perp=p.P_perp, P_tor=p.P_tor,\n", + " Q_e=4 / p.tauk, Q_i=-10 / p.tauk, iota_e=p.iota_e,\n", + " tauk=p.tauk, tau_r=p.tau_r, delta_n=p.delta_n,\n", + " rs=p.rs, R0=p.R0, bt=p.bt, sval_r=p.sval_r,\n", + " dr_val=p.dr_val, dgeo_val=p.dgeo_val,\n", + " eta=p.eta, d_beta=p.d_beta,\n", + " dc_tmp=p.dc_tmp, dc_type=p.dc_type\n", + ")\n", "\n", - " positive = isfinite.(bal) .& (bal .> 0.0)\n", + "#p = p2\n", "\n", - " if !any(positive)\n", - " return Qs, bal, Float64[], Float64[], NaN, NaN, 0, Δs\n", - " end\n", + "tb = TorqueBalance(\n", + " GeneralizedPerturbedEquilibrium.InnerLayer.SLAYERModel(;),\n", + " p,\n", + " 0.5,\n", + " 1.0,\n", + " p.lu,\n", + " p.sval_r\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4", + "metadata": {}, + "outputs": [], + "source": [ + "#Qs = range(-5.0, 5.0, length=200)\n", "\n", - " i = argmax(bal)\n", - " Qpeak_ind = i\n", - " Qs_positive = Qs[positive]\n", - " bal_positive = bal[positive]\n", + "#vals = [torque_balance_value(tb, q) for q in Qs]\n", + "\"\"\"\n", + "n=2000:\n", + "Qpeak = 0.24512256128064033\n", + "maxbal = 0.35873684252530247\n", + "br_crit = 4.668551985584323e-5\n", "\n", - " i = argmax(bal_positive)\n", - " Qpeak = Qs_positive[i]\n", - " maxbal = bal_positive[i]\n", + "n=200 (def):\n", + "Qpeak = 0.25125628140703515\n", + "maxbal = 0.3585219071071706\n", + "br_crit = 4.667153206033017e-5\n", + "\"\"\"\n", + "Qs, bal, Qs_positive, bal_positive, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb)\n", "\n", - " br_crit = sqrt(maxbal / tb.lu * (tb.sval^2 / 2.0))\n", - " return Qs, bal, Qs_positive, bal_positive, Qpeak, br_crit, Qpeak_ind, Δs\n", - "end\n", - "# one-cell scan: x = b_crit, y = Q_0\n", - "Q0_vals = range(-2.0, 2.0; length=60)\n", + "println(\"Qpeak = \", Qpeak)\n", + "println(\"maxbal = \", maximum(bal_positive))\n", + "println(\"maxbal = \", maximum(bal))\n", + "println(\"br_crit = \", brcrit)\n", "\n", - "bcrit_vals = Float64[]\n", - "locked_flag = Bool[]\n", + "p1 = plot(Qs, bal, lw=2, label=\"balance\")\n", + "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", + "xlabel!(\"Q\")\n", + "ylabel!(\"balance\")\n", + "title!(\"Torque-balance scan\")\n", "\n", - "for Q0 in Q0_vals\n", - " tbQ = TorqueBalance(\n", - " tb.model,\n", - " tb.params,\n", - " Float64(Q0),\n", - " tb.P,\n", - " tb.delta_n_p,\n", - " tb.lu,\n", - " tb.sval\n", - " )\n", + "p2 = plot(Qs_positive, bal_positive, lw=2, label=\"balance (positive)\")\n", + "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", + "xlabel!(\"Q\")\n", + "ylabel!(\"balance\")\n", + "title!(\"Torque-balance scan\")\n", "\n", - " Qs, bal, Qs_pos, bal_pos, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tbQ; Qmin=-10.0, Qmax=10.0, n=250)\n", + "plot(p1, p2, layout=(2,1), size=(800, 1000))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5", + "metadata": {}, + "outputs": [], + "source": [ + "Qpk = Qs_positive[argmax(bal_positive)]\n", + "j = findfirst(isequal(Qpk), Qs)\n", "\n", - " if isempty(bal_pos) || !all(isfinite.(bal_pos)) || maximum(bal_pos) <= 0\n", - " push!(bcrit_vals, NaN)\n", - " push!(locked_flag, false)\n", - " else\n", - " push!(bcrit_vals, brcrit)\n", - " push!(locked_flag, true)\n", - " end\n", - "end\n", + "lhs = 2*tb.P*(tb.Q0 - Qpk) / jxbs[j]\n", + "br_ratio = sqrt(lhs / (tb.lu * tb.sval^2 / 2))\n", "\n", - "# keep only finite x-values for plotting\n", - "x = bcrit_vals[isfinite.(bcrit_vals)]\n", - "y = Q0_vals[isfinite.(bcrit_vals)]\n", - "locked = locked_flag[isfinite.(bcrit_vals)]\n", - "\n", - "p = scatter(\n", - " x[locked], y[locked],\n", - " label=\"locked\",\n", - " color=:green,\n", - " markersize=5,\n", - " marker=:circle,\n", - " xlabel=\"b_crit\",\n", - " ylabel=\"Q_0\",\n", - " title=\"Locked / unlocked boundary\",\n", - " legend=:topleft\n", - ")\n", + "rhs = (tb.lu * tb.sval^2 / 2) * br_ratio^2\n", "\n", - "scatter!(\n", - " p,\n", - " x[.!locked], y[.!locked],\n", - " label=\"unlocked\",\n", - " color=:red,\n", - " markersize=5,\n", - " marker=:square\n", - ")\n", "\n", - "display(p)" + "\n", + "println(\"lhs = \", lhs)\n", + "println(\"rhs = \", rhs)\n", + "println(\"lhs/rhs = \", lhs / rhs)" ] }, { "cell_type": "code", "execution_count": null, - "id": "5", + "id": "6", "metadata": {}, "outputs": [], "source": [ - "import Pkg; Pkg.add(\"DataInterpolations\")" + "#Δs = [solve_inner(tb.model, tb.params, ComplexF64(q)).tearing for q in Qs]\n", + "jxbs = [-imag(1.0 / (d + tb.delta_n_p)) for d in Δs]\n", + "T_VISC = [2.0 * tb.P * (tb.Q0 - q) for (q, jxb) in zip(Qs, jxbs)]\n", + "br_t = brcrit\n", + "println(tb.lu, \" \", tb.sval, \" \", br_t, \" \", p.bt, \" \", tb.delta_n_p)\n", + "T_EM = tb.lu * tb.sval^2/2 * (brcrit)^2 * jxbs\n", + "i = Qpeak_ind\n", + "println(T_VISC[i]/(tb.lu * tb.sval^2/2 * (brcrit)^2 * jxbs[i]))\n", + "println(T_VISC[i] / (tb.lu * tb.sval^2/2 * (brcrit * p.bt)^2 * jxbs[i]))\n", + "println(T_VISC[i] / ( (brcrit / p.bt)^2 * jxbs[i]))\n", + "\n", + "#T_EM ∝ S ξ̂ (br/Bφ)² Im[-Δ̂(Q)⁻¹]\n", + "#T_visc ∝ 2 P (Q0 − Q)\n", + "\n", + "p1 = plot(Qs, imag.(Δs), label=\"Im(Δ)\", lw=2)\n", + "#plot!(p1, Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", + "xlabel!(p1, \"Q\")\n", + "ylabel!(p1, \"Δ\")\n", + "title!(p1, \"Inner-layer Δ(Q)\")\n", + "\n", + "p2 = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", + "plot!(p2, Qs, T_VISC, label=\"2P(Q0-Q)\", lw=2)\n", + "plot!(p2, Qs, T_EM, label=\"T_EM\", lw=2)\n", + "xlabel!(p2, \"Q\")\n", + "ylabel!(p2, \"jxb\")\n", + "title!(p2, \"jxb(Q) = -Im[1/(Δ + δ_n_p)]\")\n", + "\n", + "p3 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2)\n", + "plot!(p3, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", + "xlabel!(p3, \"Q\")\n", + "ylabel!(p3, \"balance\")\n", + "title!(p3, \"2P(Q0-Q)/jxb\")\n", + "\n", + "plot(p1, p2, p3, layout=(3,1), size=(800, 1000))" ] }, { "cell_type": "code", "execution_count": null, - "id": "6", + "id": "7", "metadata": {}, "outputs": [], "source": [ + "# Recreate Cihan's plot:\n", + "\n", "using Plots\n", "using DataInterpolations\n", "\n", @@ -300,54 +349,13 @@ "display(p)" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "7", - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "code", "execution_count": null, "id": "8", "metadata": {}, "outputs": [], - "source": [ - "# You can substitute any valid SLAYERParameters you already have.\n", - "# This is just an example skeleton.\n", - "p = GeneralizedPerturbedEquilibrium.InnerLayer.slayer_parameters(\n", - " n_e=1e19, t_e=1e3, t_i=1e3,\n", - " omega=0.0, omega_e=4, omega_i=-2,\n", - " qval=2.0, sval_r=0.5, bt=2.0, rs=1.0, R0=3.0, mu_i=2.0, zeff=1.0,\n", - " chi_perp=1.0, chi_tor=1.0, m=2, n=1\n", - ")\n", - "p2 = GeneralizedPerturbedEquilibrium.InnerLayer.SLAYERParameters(\n", - " ising=p.ising,\n", - " m=p.m, n=p.n,\n", - " tau=p.tau, lu=p.lu, c_beta=p.c_beta, D_norm=p.D_norm,\n", - " P_perp=p.P_perp, P_tor=p.P_tor,\n", - " Q_e=4 / p.tauk, Q_i=-10 / p.tauk, iota_e=p.iota_e,\n", - " tauk=p.tauk, tau_r=p.tau_r, delta_n=p.delta_n,\n", - " rs=p.rs, R0=p.R0, bt=p.bt, sval_r=p.sval_r,\n", - " dr_val=p.dr_val, dgeo_val=p.dgeo_val,\n", - " eta=p.eta, d_beta=p.d_beta,\n", - " dc_tmp=p.dc_tmp, dc_type=p.dc_type\n", - ")\n", - "\n", - "#p = p2\n", - "\n", - "tb = TorqueBalance(\n", - " GeneralizedPerturbedEquilibrium.InnerLayer.SLAYERModel(;),\n", - " p,\n", - " 0.5,\n", - " 1.0,\n", - " 1e-2,\n", - " p.lu,\n", - " p.sval_r\n", - ")" - ] + "source": [] }, { "cell_type": "code", @@ -355,141 +363,7 @@ "id": "9", "metadata": {}, "outputs": [], - "source": [ - "\"\"\"\n", - "\n", - "tau_h=R0*(mu0*rho)**0.5/(nns*sval*bt) ! alfven time across surface\n", - "lu=tau_r/tau_h ! Lundquist number\n", - "Qconv=lu**(1.0/3.0)*tau_h ! conversion to Qs based on Cole\n", - "\n", - "! note Q depends on Qconv even if omega is fixed.\n", - "Q=Qconv*omega\n", - "Q_e=-Qconv*omega_e\n", - "Q_i=-Qconv*omega_i\n", - "\n", - "\"\"\"\n", - "2=-lu**(1.0/3.0)*tau_h *OE\n", - "2 = tauk *OE" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "10", - "metadata": {}, - "outputs": [], - "source": [ - "Qs = range(-5.0, 5.0, length=200)\n", - "\n", - "vals = [torque_balance_value(tb, q) for q in Qs]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "11", - "metadata": {}, - "outputs": [], - "source": [ - "\"\"\"\n", - "n=2000:\n", - "Qpeak = 0.24512256128064033\n", - "maxbal = 0.35873684252530247\n", - "br_crit = 4.668551985584323e-5\n", - "\n", - "n=200 (def):\n", - "Qpeak = 0.25125628140703515\n", - "maxbal = 0.3585219071071706\n", - "br_crit = 4.667153206033017e-5\n", - "\"\"\"\n", - "Qs, bal, Qs_positive, bal_positive, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb)\n", - "\n", - "println(\"Qpeak = \", Qpeak)\n", - "println(\"maxbal = \", maximum(bal_positive))\n", - "println(\"maxbal = \", maximum(bal))\n", - "println(\"br_crit = \", brcrit)\n", - "\n", - "p1 = plot(Qs, bal, lw=2, label=\"balance\")\n", - "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", - "xlabel!(\"Q\")\n", - "ylabel!(\"balance\")\n", - "title!(\"Torque-balance scan\")\n", - "\n", - "p2 = plot(Qs_positive, bal_positive, lw=2, label=\"balance (positive)\")\n", - "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", - "xlabel!(\"Q\")\n", - "ylabel!(\"balance\")\n", - "title!(\"Torque-balance scan\")\n", - "\n", - "plot(p1, p2, layout=(2,1), size=(800, 1000))\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "12", - "metadata": {}, - "outputs": [], - "source": [ - "Qpk = Qs_positive[argmax(bal_positive)]\n", - "j = findfirst(isequal(Qpk), Qs)\n", - "\n", - "lhs = 2*tb.P*(tb.Q0 - Qpk) / jxbs[j]\n", - "br_ratio = sqrt(lhs / (tb.lu * tb.sval^2 / 2))\n", - "\n", - "rhs = (tb.lu * tb.sval^2 / 2) * br_ratio^2\n", - "\n", - "\n", - "\n", - "println(\"lhs = \", lhs)\n", - "println(\"rhs = \", rhs)\n", - "println(\"lhs/rhs = \", lhs / rhs)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "13", - "metadata": {}, - "outputs": [], - "source": [ - "#Δs = [solve_inner(tb.model, tb.params, ComplexF64(q)).tearing for q in Qs]\n", - "jxbs = [-imag(1.0 / (d + tb.delta_n_p)) for d in Δs]\n", - "T_VISC = [2.0 * tb.P * (tb.Q0 - q) for (q, jxb) in zip(Qs, jxbs)]\n", - "br_t = brcrit\n", - "println(tb.lu, \" \", tb.sval, \" \", br_t, \" \", p.bt, \" \", tb.delta_n_p)\n", - "T_EM = tb.lu * tb.sval^2/2 * (brcrit)^2 * jxbs\n", - "i = Qpeak_ind\n", - "println(T_VISC[i]/(tb.lu * tb.sval^2/2 * (brcrit)^2 * jxbs[i]))\n", - "println(T_VISC[i] / (tb.lu * tb.sval^2/2 * (brcrit * p.bt)^2 * jxbs[i]))\n", - "println(T_VISC[i] / ( (brcrit / p.bt)^2 * jxbs[i]))\n", - "\n", - "#T_EM ∝ S ξ̂ (br/Bφ)² Im[-Δ̂(Q)⁻¹]\n", - "#T_visc ∝ 2 P (Q0 − Q)\n", - "\n", - "p1 = plot(Qs, imag.(Δs), label=\"Im(Δ)\", lw=2)\n", - "#plot!(p1, Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", - "xlabel!(p1, \"Q\")\n", - "ylabel!(p1, \"Δ\")\n", - "title!(p1, \"Inner-layer Δ(Q)\")\n", - "\n", - "p2 = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", - "plot!(p2, Qs, T_VISC, label=\"2P(Q0-Q)\", lw=2)\n", - "plot!(p2, Qs, T_EM, label=\"T_EM\", lw=2)\n", - "xlabel!(p2, \"Q\")\n", - "ylabel!(p2, \"jxb\")\n", - "title!(p2, \"jxb(Q) = -Im[1/(Δ + δ_n_p)]\")\n", - "\n", - "p3 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2)\n", - "plot!(p3, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", - "xlabel!(p3, \"Q\")\n", - "ylabel!(p3, \"balance\")\n", - "title!(p3, \"2P(Q0-Q)/jxb\")\n", - "\n", - "plot(p1, p2, p3, layout=(3,1), size=(800, 1000))" - ] + "source": [] } ], "metadata": { diff --git a/src/Tearing/Dispersion/BruteForceScan.jl b/src/Tearing/Dispersion/BruteForceScan.jl index 6e7b8aead..c1f2b55fb 100644 --- a/src/Tearing/Dispersion/BruteForceScan.jl +++ b/src/Tearing/Dispersion/BruteForceScan.jl @@ -15,12 +15,12 @@ Output of a brute-force or AMR Q-plane scan. -| field | meaning | -|------------|---------------------------------------------------| -| `Q` | Complex Q values (`Matrix` for grid, `Vector` for AMR) | -| `Δ` | Residual values, same shape as `Q` | -| `re_axis` | Real-axis grid (only for regular-grid `ScanResult`) | -| `im_axis` | Imaginary-axis grid (only for regular-grid `ScanResult`) | +| field | meaning | +|:--------- |:-------------------------------------------------------- | +| `Q` | Complex Q values (`Matrix` for grid, `Vector` for AMR) | +| `Δ` | Residual values, same shape as `Q` | +| `re_axis` | Real-axis grid (only for regular-grid `ScanResult`) | +| `im_axis` | Imaginary-axis grid (only for regular-grid `ScanResult`) | """ struct ScanResult Q::Matrix{ComplexF64} @@ -53,15 +53,15 @@ from the result. - `threaded` -- distribute Q evaluations across `Threads.@threads` """ function brute_force_scan(f, Q_re_range::NTuple{2,<:Real}, - Q_im_range::NTuple{2,<:Real}; - nre::Integer, nim::Integer, - threaded::Bool=true) + Q_im_range::NTuple{2,<:Real}; + nre::Integer, nim::Integer, + threaded::Bool=true) nre >= 2 || throw(ArgumentError("brute_force_scan: nre must be ≥ 2")) nim >= 2 || throw(ArgumentError("brute_force_scan: nim must be ≥ 2")) re_axis = collect(range(Float64(Q_re_range[1]); stop=Float64(Q_re_range[2]), - length=nre)) + length=nre)) im_axis = collect(range(Float64(Q_im_range[1]); stop=Float64(Q_im_range[2]), - length=nim)) + length=nim)) Q = ComplexF64[(qr + qi*im) for qr in re_axis, qi in im_axis] Δ = Matrix{ComplexF64}(undef, nre, nim) if threaded diff --git a/src/Tearing/Dispersion/ContourSearchAMR.jl b/src/Tearing/Dispersion/ContourSearchAMR.jl index 3533a1773..5cf369eda 100644 --- a/src/Tearing/Dispersion/ContourSearchAMR.jl +++ b/src/Tearing/Dispersion/ContourSearchAMR.jl @@ -243,7 +243,7 @@ function amr_scan(f, Q_re_range::NTuple{2,<:Real}, _bulk_eval_into_cache!(cache, f, corners; parallel=parallel) cells = Vector{AMRCell}(undef, nre0 * nim0) - @inbounds for j in 0:nim0-1, i in 0:nre0-1 + @inbounds for j in 0:(nim0-1), i in 0:(nre0-1) # Read corner Q values from the same `corners` array used to populate # the cache. Recomputing them with `x + re_step` here would differ in # the last floating-point bit from the cache keys, causing spurious @@ -573,7 +573,7 @@ function multi_box_amr_scan(f, # Build pre-screen cells ps_cells = Vector{AMRCell}(undef, prescreen_nre * prescreen_nim) - @inbounds for j in 0:prescreen_nim-1, i in 0:prescreen_nre-1 + @inbounds for j in 0:(prescreen_nim-1), i in 0:(prescreen_nre-1) q_bl = corners[j*ncorners_x+i+1] q_br = corners[j*ncorners_x+(i+1)+1] q_tl = corners[(j+1)*ncorners_x+i+1] diff --git a/src/Tearing/Dispersion/CoupledFullMatch.jl b/src/Tearing/Dispersion/CoupledFullMatch.jl index 9b0f136c9..ed68c4445 100644 --- a/src/Tearing/Dispersion/CoupledFullMatch.jl +++ b/src/Tearing/Dispersion/CoupledFullMatch.jl @@ -155,7 +155,7 @@ function (mc::MultiSurfaceCouplingFull)(Q::Number) # Allocate the matching matrix and fill the lower-left 2m × 2m block # with transpose(dp_raw[1:s2, 1:s2]). mat = zeros(ComplexF64, s4, s4) - @views mat[s2+1:s4, 1:s2] .= transpose(mc.dp_raw[1:s2, 1:s2]) + @views mat[(s2+1):s4, 1:s2] .= transpose(mc.dp_raw[1:s2, 1:s2]) # Per-surface inner-layer assembly @inbounds for k in 1:m diff --git a/src/Tearing/Dispersion/GrowthRateExtraction.jl b/src/Tearing/Dispersion/GrowthRateExtraction.jl index 42c2c9681..796e67633 100644 --- a/src/Tearing/Dispersion/GrowthRateExtraction.jl +++ b/src/Tearing/Dispersion/GrowthRateExtraction.jl @@ -253,10 +253,10 @@ function _all_intersections(re_paths::Vector{Vector{ComplexF64}}, im_paths::Vector{Vector{ComplexF64}}) out = ComplexF64[] for re_path in re_paths - for i in 1:length(re_path)-1 + for i in 1:(length(re_path)-1) a, b = re_path[i], re_path[i+1] for im_path in im_paths - for j in 1:length(im_path)-1 + for j in 1:(length(im_path)-1) c, d = im_path[j], im_path[j+1] pt = _segment_intersection(a, b, c, d) pt !== nothing && push!(out, pt) @@ -468,7 +468,7 @@ function _median_segment_length(re_paths::Vector{Vector{ComplexF64}}, im_paths::Vector{Vector{ComplexF64}}) lens = Float64[] for paths in (re_paths, im_paths), p in paths - @inbounds for i in 1:length(p)-1 + @inbounds for i in 1:(length(p)-1) push!(lens, abs(p[i+1] - p[i])) end end @@ -811,7 +811,7 @@ function _march_triangle(p1::ComplexF64, p2::ComplexF64, p3::ComplexF64, v1::ComplexF64, v2::ComplexF64, v3::ComplexF64, re_target::Float64, im_target::Float64) return (_march_single(p1, p2, p3, real(v1), real(v2), real(v3), - imag(v1), imag(v2), imag(v3), re_target), + imag(v1), imag(v2), imag(v3), re_target), _march_single(p1, p2, p3, imag(v1), imag(v2), imag(v3), real(v1), real(v2), real(v3), im_target)) end diff --git a/src/Tearing/Runner/Control.jl b/src/Tearing/Runner/Control.jl index 1a12ff7e6..88e8fe091 100644 --- a/src/Tearing/Runner/Control.jl +++ b/src/Tearing/Runner/Control.jl @@ -4,6 +4,9 @@ # growth-rate analysis. Populated either directly via the `@kwdef` # constructor or by parsing the `[SLAYER]` (and nested `[SLAYER.*]`) # section(s) of a `gpec.toml`. +# +# `CriticalResonantFieldControl` holds the user-facing knobs that drive the critical resonant field +# analysis. Populated either directly via the `@kwdef` constructor or by parsing the `[CriticalResonantField]` section of a `gpec.toml`. """ SLAYERControl @@ -268,3 +271,41 @@ function slayer_control_from_toml(section::AbstractDict) end return validate(SLAYERControl(; kwargs...)) end + +""" + CriticalResonantFieldControl + +Configuration for the critical resonant field analysis. All fields are +user-facing: read from the `[CriticalResonantField]` TOML section of a `gpec.toml` via +`critical_resonant_field_control_from_toml`, or built directly via the `@kwdef` keyword +constructor. +""" +@kwdef struct CriticalResonantFieldControl + enabled::Bool = false + inner_model::Symbol = :slayer_fitzpatrick + Qmin::Float64 = -10.0 + Qmax::Float64 = 10.0 + n::Int = 200 + profile_file::String = "" + profile_group::String = "/" + store_scan::Bool = false +end + +function critical_resonant_field_control_from_toml(section::AbstractDict) + flat = Dict{String,Any}() + for (k, v) in section + flat[k] = v + end + + kwargs = Dict{Symbol,Any}() + for (k, v) in flat + sym = Symbol(k) + if sym in (:inner_model,) + kwargs[sym] = v isa Symbol ? v : Symbol(String(v)) + else + kwargs[sym] = v + end + end + + return CriticalResonantFieldControl(; kwargs...) +end diff --git a/src/Tearing/Runner/HDF5Output.jl b/src/Tearing/Runner/HDF5Output.jl index ca4287147..02c3f5da9 100644 --- a/src/Tearing/Runner/HDF5Output.jl +++ b/src/Tearing/Runner/HDF5Output.jl @@ -1,6 +1,6 @@ # HDF5Output.jl # -# Write a `SLAYERResult` into an HDF5 group. Designed to be called by the +# Write a `SLAYERResult` or `CriticalResonantFieldResult` into an HDF5 group. Designed to be called by the # existing `PerturbedEquilibrium.write_outputs_to_HDF5` path — the # top-level GPEC runner wires that up; this file only defines the pure # writer. @@ -57,6 +57,38 @@ function write_slayer_hdf5!(parent::Union{HDF5.File,HDF5.Group}, return g end +function write_critical_resonant_field_hdf5!(parent::Union{HDF5.File,HDF5.Group}, + result::CriticalResonantFieldResult) + + if !haskey(parent, "Tearing") + create_group(parent, "Tearing") + end + g = create_group(parent["Tearing"], "CriticalResonantField") + + g["surface_index"] = result.surface_index + g["Qpeak"] = result.Qpeak + g["br_crit"] = result.br_crit + g["Q0"] = result.Q0 + g["P"] = result.P + + if !isempty(result.scan_data) + scan_group = create_group(g, "Scan") + for d in result.scan_data + sg = create_group(scan_group, "surface_$(d.surface)") + sg["Q"] = d.Q + sg["balance"] = d.balance + sg["delta"] = d.delta + sg["Q_positive"] = d.Q_positive + sg["balance_positive"] = d.balance_positive + sg["Qpeak"] = d.Qpeak + sg["br_crit"] = d.br_crit + end + end + + attrs(g)["kind"] = "critical_resonant_field" + return g +end + # Token recorded in the Tearing group's layer_model attribute; keyed by the # per-surface parameter type since the SLAYER and GGJ branches write disjoint fields. _layer_model_token(::Type{SLAYERParameters}) = "slayer" diff --git a/src/Tearing/Runner/Result.jl b/src/Tearing/Runner/Result.jl index 0cffc21c9..9132e8421 100644 --- a/src/Tearing/Runner/Result.jl +++ b/src/Tearing/Runner/Result.jl @@ -3,6 +3,10 @@ # `SLAYERResult` packages the output of a full SLAYER analysis run: # per-surface layer parameters, the extracted tearing eigenvalues, and (if # `control.store_scan`) the full Q-plane scan data for plotting. +# +# `CriticalResonantFieldResult` packages the output of the critical resonant field analysis run: +# per-surface critical resoant field. If `control.store_scan` is true, the full Q scan data, +# viscous torque, and electromagnetic torque are also stored for plotting. """ SLAYERResult @@ -22,9 +26,9 @@ downstream inspection and HDF5 output. the surface list), in which case the HDF5 writer skips them. - `dp_matrix` -- outer-region Δ' matrix used in the analysis - `Q_root` -- tearing eigenvalue(s) in normalized Q - * length `nsurfaces` in `:uncoupled` mode - * length `1` in `:coupled` mode (global eigenvalue normalized by - `params[1].tauk`) + + length `nsurfaces` in `:uncoupled` mode + + length `1` in `:coupled` mode (global eigenvalue normalized by + `params[1].tauk`) - `omega_Hz`, `gamma_Hz` -- physical rotation frequency / growth rate - `per_surface_extraction` -- `Vector{GrowthRateResult}` of length `nsurfaces` in uncoupled mode (each includes polelines, pole list, @@ -64,3 +68,33 @@ function empty_slayer_result(control::SLAYERControl) LayerWidths[], Union{ScanResult,AMRResult}[]) end + +""" + CriticalResonantFieldResult + +Output of `run_critical_resonant_field`. Carries both summary critical resonant field values and if `control.store_scan` is true, the full Q scan data, viscous torque, and electromagnetic torque for plotting. +""" + +struct CriticalResonantFieldResult + enabled::Bool + params::AbstractVector{<:InnerLayerParameters} + surface_index::Vector{Int} + Qpeak::Vector{Float64} + br_crit::Vector{Float64} + Q0::Vector{Float64} + P::Vector{Float64} + scan_data::Vector{NamedTuple} +end + +function empty_critical_resonant_field_result() + return CriticalResonantFieldResult( + false, + InnerLayerParameters[], + Int[], + Float64[], + Float64[], + Float64[], + Float64[], + NamedTuple[] + ) +end diff --git a/src/Tearing/Runner/Runner.jl b/src/Tearing/Runner/Runner.jl index 919088065..df3293b2f 100644 --- a/src/Tearing/Runner/Runner.jl +++ b/src/Tearing/Runner/Runner.jl @@ -32,11 +32,14 @@ using ..Utilities using ..Utilities: KineticProfiles using ...Equilibrium: read_kinetic_file, KineticProfileData using ..InnerLayer -using ..InnerLayer: InnerLayerParameters, InnerLayerResponse, solve_inner, +using ..InnerLayer: + InnerLayerParameters, InnerLayerResponse, solve_inner, SLAYERModel, SLAYERParameters, build_slayer_inputs, GGJModel, GGJParameters, LayerWidths, slayer_layer_thickness import ..build_ggj_inputs # defined at the Tearing level (needs ForceFreeStates) +import ...Equilibrium as Equilibrium +using ...Equilibrium: read_kinetic_file, KineticProfileData, load_kinetic_profiles using ..Dispersion using ..Dispersion: SurfaceCoupling, surface_coupling, MultiSurfaceCoupling, multi_surface_coupling, @@ -54,5 +57,9 @@ export SLAYERControl, slayer_control_from_toml, validate export SLAYERResult, empty_slayer_result export run_slayer, run_slayer_from_inputs, ggj_inner_deltas export write_slayer_hdf5! +export CriticalResonantFieldControl, critical_resonant_field_control_from_toml +export CriticalResonantFieldResult, empty_critical_resonant_field_result +export run_critical_resonant_field +export write_critical_resonant_field_hdf5! end # module Runner diff --git a/src/Tearing/Runner/run_slayer.jl b/src/Tearing/Runner/run_slayer.jl index 2a29c63a8..3dca41bbc 100644 --- a/src/Tearing/Runner/run_slayer.jl +++ b/src/Tearing/Runner/run_slayer.jl @@ -455,3 +455,82 @@ function run_slayer(equil, surfaces::AbstractVector, delta_prime_matrix::Abstrac rational_q = Float64[surfaces[p.ising].q for p in params] return run_slayer_from_inputs(params, dp, control; rational_psi=rational_psi, rational_q=rational_q) end + +# --------------------------------------------------------------------- +# Critical Resonant Field (Torque-Balance) Workflow +# --------------------------------------------------------------------- +""" + Critical Resonant Field (Torque-Balance) Workflow + + The critical resonant field is the minimum resonant magnetic perturbation + amplitude that can drive a tearing mode unstable. + + Returns a `CriticalResonantFieldResult` containing the critical resonant field + and the corresponding critical resoannt field values for each rational surface. +""" + +function run_critical_resonant_field(equil, intr, ctrl; dir_path="./") + ctrl.enabled || return empty_critical_resonant_field_result() + + # Use the same per-surface params already built for SLAYER + profiles = Equilibrium.load_kinetic_profiles(joinpath(dir_path, ctrl.profile_file)) + params = build_slayer_inputs(equil, intr.sing, profiles) + + surface_index = Int[] + Qpeak_vec = Float64[] + br_vec = Float64[] + Q0_vec = Float64[] + P_vec = Float64[] + scan_data = NamedTuple[] + + for (isurf, p) in enumerate(params) + # Fill in the actual per-surface drive from your model + Q0_here = 0.5 + P_here = 1.0 + + tb = TorqueBalance( + SLAYERModel{:fitzpatrick}(), + p, + Q0_here, + P_here, + p.lu, + p.sval_r + ) + + Qs, bal, Qs_positive, bal_positive, Qpeak, br_crit, Qpeak_ind, Δs = + torque_balance_scan(tb; Qmin=ctrl.Qmin, Qmax=ctrl.Qmax, n=ctrl.n) + + push!(surface_index, isurf) + push!(Qpeak_vec, Qpeak) + push!(br_vec, br_crit) + push!(Q0_vec, Q0_here) + push!(P_vec, P_here) + + if ctrl.store_scan + push!( + scan_data, + ( + surface=isurf, + Q=collect(Qs), + balance=collect(bal), + delta=collect(Δs), + Q_positive=collect(Qs_positive), + balance_positive=collect(bal_positive), + Qpeak=Qpeak, + br_crit=br_crit + ) + ) + end + end + + return CriticalResonantFieldResult( + true, + params, + surface_index, + Qpeak_vec, + br_vec, + Q0_vec, + P_vec, + scan_data + ) +end diff --git a/src/Tearing/Tearing.jl b/src/Tearing/Tearing.jl index ae3ed8e3c..3ebd35996 100644 --- a/src/Tearing/Tearing.jl +++ b/src/Tearing/Tearing.jl @@ -6,6 +6,8 @@ # InnerLayer -- pure physics: Δ_inner(Q) for GGJ or SLAYER models # Dispersion -- physics-agnostic scan + contour-intersection root # extraction (consumes any InnerLayerModel) +# CriticalResonantField -- physics-agnostic scan + torque-balance root +# extraction (consumes any InnerLayerModel) # Runner -- user-facing orchestration: TOML config, profile # loading, HDF5 output, workflow hooks # diff --git a/src/Utilities/GridUtilities.jl b/src/Utilities/GridUtilities.jl index a02bf0d08..71e255699 100644 --- a/src/Utilities/GridUtilities.jl +++ b/src/Utilities/GridUtilities.jl @@ -11,25 +11,27 @@ Power-law spaced grid with analytic derivative calculation. Creates a grid with more points concentrated near boundaries. # Arguments -- `x_min, x_max`: Grid boundaries -- `npower::Int`: Power law exponent (1=linear, higher=more concentration at edges) -- `nx::Int`: Number of grid points -- `spacing::String`: "lower" (concentrate at x_min), "upper" (at x_max), or "both" + + - `x_min, x_max`: Grid boundaries + - `npower::Int`: Power law exponent (1=linear, higher=more concentration at edges) + - `nx::Int`: Number of grid points + - `spacing::String`: "lower" (concentrate at x_min), "upper" (at x_max), or "both" # Returns -- `Matrix{Float64}`: (2, nx) where row 1 = positions, row 2 = dr/d(norm) derivatives + + - `Matrix{Float64}`: (2, nx) where row 1 = positions, row 2 = dr/d(norm) derivatives """ function powspace(x_min::Float64, x_max::Float64, npower::Int, nx::Int, - spacing::String)::Matrix{Float64} + spacing::String)::Matrix{Float64} result = zeros(Float64, 2, nx) y = if spacing == "lower" - collect(range(-1.0, 0.0, length=nx)) + collect(range(-1.0, 0.0; length=nx)) elseif spacing == "upper" - collect(range(0.0, 1.0, length=nx)) + collect(range(0.0, 1.0; length=nx)) elseif spacing == "both" - collect(range(-1.0, 1.0, length=nx)) + collect(range(-1.0, 1.0; length=nx)) else error("Unknown spacing type: $spacing. Use \"lower\", \"upper\", or \"both\".") end @@ -78,10 +80,10 @@ end function _powspace_numeric_integral(y::Float64, npower::Int)::Float64 y == 0.0 && return 0.0 npts = 100 - y_int = range(0.0, y, length=npts) + y_int = range(0.0, y; length=npts) f_int = abs.((y_int .- 1) .* (y_int .+ 1)) .^ npower integral = (f_int[1] + f_int[npts]) / 2 - for i in 2:(npts - 1) + for i in 2:(npts-1) integral += f_int[i] end return integral * (y / (npts - 1)) diff --git a/src/Utilities/HDF5Annotations.jl b/src/Utilities/HDF5Annotations.jl index 1fff44e62..33e055b4f 100644 --- a/src/Utilities/HDF5Annotations.jl +++ b/src/Utilities/HDF5Annotations.jl @@ -7,8 +7,7 @@ Self-describing metadata for `gpec.h5` (the contract in datasets are marked as HDF5 Dimension Scales (netCDF-4 coordinate variables) attached to the arrays that share their axis, so h5py/xarray/HDFView read the file unaided. -Writers stay table-driven: each writer keeps a table of `path => (; long_name, units, -dims)` entries next to it and calls [`annotate!`](@ref) once after its datasets are +Writers stay table-driven: each writer keeps a table of `path => (; long_name, units, dims)` entries next to it and calls [`annotate!`](@ref) once after its datasets are written. Paths absent from the file are skipped silently (many writes are conditional). """ module HDF5Annotations diff --git a/src/Utilities/PhysicalConstants.jl b/src/Utilities/PhysicalConstants.jl index a9668b611..6511e6df2 100644 --- a/src/Utilities/PhysicalConstants.jl +++ b/src/Utilities/PhysicalConstants.jl @@ -10,11 +10,11 @@ All quantities in SI units. module PhysicalConstants # Match the Fortran GPEC/SLAYER sglobal_mod values exactly so cross-code numerical comparison is meaningful. -const MU_0 = 4.0e-7 * π # vacuum permeability [H/m] -const M_E = 9.1094e-31 # electron mass [kg] -const M_P = 1.6726e-27 # proton mass [kg] +const MU_0 = 4.0e-7 * π # vacuum permeability [H/m] +const M_E = 9.1094e-31 # electron mass [kg] +const M_P = 1.6726e-27 # proton mass [kg] const E_CHG = 1.6021917e-19 # elementary charge [C] -const K_B = 1.3807e-23 # Boltzmann constant [J/K] +const K_B = 1.3807e-23 # Boltzmann constant [J/K] const EPS_0 = 8.8542e-12 # vacuum permittivity [F/m] export MU_0, M_E, M_P, E_CHG, K_B, EPS_0 diff --git a/src/Vacuum/PnQuadCache.jl b/src/Vacuum/PnQuadCache.jl index 6e0b8b719..4d6de9850 100644 --- a/src/Vacuum/PnQuadCache.jl +++ b/src/Vacuum/PnQuadCache.jl @@ -26,7 +26,7 @@ const _PN_BGAUS = 2.5 const (_PN_TG02, _PN_WANUMR) = let x32, w32 = gausslegendre(32) tg0 = [_PN_AGAUS + x32[i] * _PN_BGAUS for i in 1:32] - tg02 = NTuple{32,Float64}(t * t for t in tg0) + tg02 = NTuple{32,Float64}(t * t for t in tg0) wanumr = NTuple{32,Float64}(w32[i] * tg0[i] * exp(-tg0[i]^2) for i in 1:32) (tg02, wanumr) end @@ -94,17 +94,19 @@ end function _make_pn_quad_entry(n::Int) @assert n >= 1 "PnQuadEntry is only defined for n ≥ 1 (Γ(1/2 - n) diverges at n = 0)" - inv_2n = 1.0 / (2.0 * n) + inv_2n = 1.0 / (2.0 * n) inv_2np2 = 1.0 / (2.0 * n + 2.0) - sh = Vector{Float64}(undef, 32) - ch = Vector{Float64}(undef, 32) + sh = Vector{Float64}(undef, 32) + ch = Vector{Float64}(undef, 32) shp = Vector{Float64}(undef, 32) chp = Vector{Float64}(undef, 32) @inbounds for ig in 1:32 - x = _PN_TG02[ig] * inv_2n + x = _PN_TG02[ig] * inv_2n xp = _PN_TG02[ig] * inv_2np2 - sh[ig] = sinh(x); ch[ig] = cosh(x) - shp[ig] = sinh(xp); chp[ig] = cosh(xp) + sh[ig] = sinh(x) + ch[ig] = cosh(x) + shp[ig] = sinh(xp) + chp[ig] = cosh(xp) end # Compute the Gamma function Γ(1/2 - n) via the product formula. @@ -117,7 +119,7 @@ function _make_pn_quad_entry(n::Int) # Combine into scale factors used in the final Legendre function assembly. # Pre-computing these once per n avoids repeating the Gamma product on every s-call. sqtwo = sqrt(2.0) - gauss_norm_n = sqtwo / (n * sqpi * gamn) + gauss_norm_n = sqtwo / (n * sqpi * gamn) gauss_norm_np1 = sqtwo / ((n + 1.0) * sqpi * gamp) return PnQuadEntry(sh, ch, shp, chp, gauss_norm_n, gauss_norm_np1) diff --git a/test/runtests_coordinate_invariant.jl b/test/runtests_coordinate_invariant.jl index 39b20330a..63fe773e3 100644 --- a/test/runtests_coordinate_invariant.jl +++ b/test/runtests_coordinate_invariant.jl @@ -43,31 +43,31 @@ end fm = PE.field_space_response_matrices(Λ, L, P, ϱ, S, jarea) @testset "Flux recovery contract (round-trip via R = S·A)" begin - @test R * fm.permeability / R ≈ P rtol = 1e-10 - @test R * fm.surface_inductance * R' ≈ L rtol = 1e-10 - @test R * fm.plasma_inductance * R' ≈ Λ rtol = 1e-10 - @test (R') \ fm.reluctance / R ≈ ϱ rtol = 1e-10 + @test R * fm.permeability / R ≈ P rtol = 1e-10 + @test R * fm.surface_inductance * R' ≈ L rtol = 1e-10 + @test R * fm.plasma_inductance * R' ≈ Λ rtol = 1e-10 + @test (R') \ fm.reluctance / R ≈ ϱ rtol = 1e-10 end @testset "Area-weighted (b̄) recovery via S (= flux/A²)" begin # b̄-space inductance L_b̄ = S·L̃·S† = L/A² since S·R⁻¹ = A⁻¹·I. - @test S * fm.surface_inductance * S' ≈ L ./ jarea^2 rtol = 1e-10 - @test S * fm.plasma_inductance * S' ≈ Λ ./ jarea^2 rtol = 1e-10 - @test S * fm.permeability / S ≈ P rtol = 1e-10 # similarity: A cancels + @test S * fm.surface_inductance * S' ≈ L ./ jarea^2 rtol = 1e-10 + @test S * fm.plasma_inductance * S' ≈ Λ ./ jarea^2 rtol = 1e-10 + @test S * fm.permeability / S ≈ P rtol = 1e-10 # similarity: A cancels end @testset "Internal consistency of the b̃ transform rules" begin - @test fm.permeability ≈ fm.plasma_inductance / fm.surface_inductance rtol = 1e-10 + @test fm.permeability ≈ fm.plasma_inductance / fm.surface_inductance rtol = 1e-10 L̃inv = inv(fm.surface_inductance) - @test fm.reluctance ≈ L̃inv * (fm.plasma_inductance - fm.surface_inductance) * L̃inv rtol = 1e-10 + @test fm.reluctance ≈ L̃inv * (fm.plasma_inductance - fm.surface_inductance) * L̃inv rtol = 1e-10 end @testset "Energy-scalar invariance (flux ↔ b̃)" begin Φ = ComplexF64[cis(0.3k) / k for k in 1:n] b̃ = R \ Φ # root-area-weighted field - @test dot(Φ, L \ Φ) ≈ dot(b̃, fm.surface_inductance \ b̃) rtol = 1e-10 - @test dot(Φ, Λ \ Φ) ≈ dot(b̃, fm.plasma_inductance \ b̃) rtol = 1e-10 - @test dot(Φ, ϱ * Φ) ≈ dot(b̃, fm.reluctance * b̃) rtol = 1e-10 + @test dot(Φ, L \ Φ) ≈ dot(b̃, fm.surface_inductance \ b̃) rtol = 1e-10 + @test dot(Φ, Λ \ Φ) ≈ dot(b̃, fm.plasma_inductance \ b̃) rtol = 1e-10 + @test dot(Φ, ϱ * Φ) ≈ dot(b̃, fm.reluctance * b̃) rtol = 1e-10 end @testset "Three-field vector relations (b, b̃, b̄; flux = A·b̄)" begin @@ -75,9 +75,9 @@ end b̄ = S * b̃ # area-weighted field b = (S .* sqrt(jarea)) \ b̃ # bare field b = Σ⁻¹·b̃ Φ = R * b̃ # poloidal flux - @test Φ ≈ jarea .* b̄ rtol = 1e-12 # Φ = A·b̄ - @test b̄ ≈ Φ ./ jarea rtol = 1e-12 - @test (S .* sqrt(jarea)) * b ≈ b̃ rtol = 1e-12 # Σ·b = b̃ + @test Φ ≈ jarea .* b̄ rtol = 1e-12 # Φ = A·b̄ + @test b̄ ≈ Φ ./ jarea rtol = 1e-12 + @test (S .* sqrt(jarea)) * b ≈ b̃ rtol = 1e-12 # Σ·b = b̃ end end diff --git a/test/runtests_dispersion_amr.jl b/test/runtests_dispersion_amr.jl index 014f3d019..86ed61653 100644 --- a/test/runtests_dispersion_amr.jl +++ b/test/runtests_dispersion_amr.jl @@ -13,7 +13,7 @@ # Small 2×2 initial grid → 9 unique corners amr = amr_scan(counting_f, (-1.0, 1.0), (-1.0, 1.0); - nre0=2, nim0=2, passes=0) + nre0=2, nim0=2, passes=0) @test amr isa AMRResult @test length(amr.cells) == 4 # 2×2 cells # Dedup: 9 unique corners (3×3) @@ -27,7 +27,7 @@ amr0 = amr_scan(f, (-1.0, 1.0), (-1.0, 1.0); nre0=4, nim0=4, passes=0) amr3 = amr_scan(f, (-1.0, 1.0), (-1.0, 1.0); nre0=4, nim0=4, passes=3) @test length(amr3.cells) > length(amr0.cells) - @test length(amr3.Q) > length(amr0.Q) + @test length(amr3.Q) > length(amr0.Q) # A 4×4 coarse grid is 16 cells; adding 3 refinement passes must # leave the total bounded by exponential growth of only the cells # bracketing the root (roughly linear in the path length). @@ -36,26 +36,26 @@ @testset "amr_scan: argument validation" begin @test_throws ArgumentError amr_scan(identity, (0.0, 1.0), (0.0, 1.0); - nre0=0, nim0=2, passes=1) + nre0=0, nim0=2, passes=1) @test_throws ArgumentError amr_scan(identity, (0.0, 1.0), (0.0, 1.0); - nre0=2, nim0=0, passes=1) + nre0=2, nim0=0, passes=1) @test_throws ArgumentError amr_scan(identity, (0.0, 1.0), (0.0, 1.0); - nre0=2, nim0=2, passes=-1) + nre0=2, nim0=2, passes=-1) end @testset "amr_scan: max_cells safety cap fires" begin # A pathological f that forces every cell to subdivide every pass f(Q) = 0.0 + 0.0im # identically zero → every cell crosses @test_throws ErrorException amr_scan(f, (-1.0, 1.0), (-1.0, 1.0); - nre0=4, nim0=4, passes=10, - max_cells=100) + nre0=4, nim0=4, passes=10, + max_cells=100) end @testset "find_growth_rates(AMR): single isolated root" begin Q_root = 0.42 + 0.27im f(Q) = ComplexF64(Q) - Q_root amr = amr_scan(f, (-1.0, 1.5), (-0.5, 1.0); - nre0=8, nim0=6, passes=4) + nre0=8, nim0=6, passes=4) result = find_growth_rates(amr, 1.0) @test result isa GrowthRateResult @test abs(result.Q_root - Q_root) < 1e-3 # AMR-resolution limited @@ -68,7 +68,7 @@ Q2 = -0.4 + 0.1im f(Q) = (ComplexF64(Q) - Q1) * (ComplexF64(Q) - Q2) amr = amr_scan(f, (-1.0, 1.0), (-0.3, 0.8); - nre0=10, nim0=8, passes=4) + nre0=10, nim0=8, passes=4) result = find_growth_rates(amr, 1.0) @test length(result.valid_roots) == 2 @test abs(result.Q_root - Q1) < 1e-2 @@ -79,7 +79,7 @@ Q_p = -0.5 + 0.6im f(Q) = (ComplexF64(Q) - Q_r) / (ComplexF64(Q) - Q_p) amr = amr_scan(f, (-1.5, 1.5), (-0.5, 1.5); - nre0=10, nim0=8, passes=5) + nre0=10, nim0=8, passes=5) result = find_growth_rates(amr, 1.0; pole_threshold=10.0) @test length(result.poles) >= 1 @test any(p -> abs(p - Q_p) < 0.05, result.poles) @@ -90,7 +90,7 @@ Q_root = 1.0 + 2.0im f(Q) = ComplexF64(Q) - Q_root amr = amr_scan(f, (-2.0, 3.0), (-1.0, 4.0); - nre0=8, nim0=8, passes=4) + nre0=8, nim0=8, passes=4) tauk = 5e-5 result = find_growth_rates(amr, tauk) @test result.omega_Hz ≈ real(result.Q_root) / tauk @@ -119,13 +119,13 @@ Q_root = 0.5 + 0.3im f(Q) = ComplexF64(Q) - Q_root scan = brute_force_scan(f, (-1.0, 1.0), (-0.5, 1.0); - nre=80, nim=60, threaded=false) - amr = amr_scan(f, (-1.0, 1.0), (-0.5, 1.0); - nre0=8, nim0=6, passes=4) + nre=80, nim=60, threaded=false) + amr = amr_scan(f, (-1.0, 1.0), (-0.5, 1.0); + nre0=8, nim0=6, passes=4) r_grid = find_growth_rates(scan, 1.0) - r_amr = find_growth_rates(amr, 1.0) + r_amr = find_growth_rates(amr, 1.0) @test abs(r_grid.Q_root - Q_root) < 1e-3 - @test abs(r_amr.Q_root - Q_root) < 1e-3 + @test abs(r_amr.Q_root - Q_root) < 1e-3 @test abs(r_grid.Q_root - r_amr.Q_root) < 5e-3 end @@ -140,22 +140,22 @@ Q_pin = 0.7 - 0.3im sc = surface_coupling(LinModel(0.0im, 1.0+0im), nothing, - Q_pin; scale=1.0, tauk=1.0) + Q_pin; scale=1.0, tauk=1.0) amr = amr_scan(sc, (-0.5, 1.5), (-1.0, 0.5); - nre0=8, nim0=6, passes=4) + nre0=8, nim0=6, passes=4) r = find_growth_rates(amr, sc.tauk) @test abs(r.Q_root - Q_pin) < 1e-2 # Multi-surface coupled scan through AMR Q_a, Q_b = 0.7 - 0.3im, -0.4 + 0.5im sc1 = surface_coupling(LinModel(0.0im, 1.0+0im), nothing, - ComplexF64(0); scale=1.0, tauk=1.0) + ComplexF64(0); scale=1.0, tauk=1.0) sc2 = surface_coupling(LinModel(0.0im, 1.0+0im), nothing, - ComplexF64(0); scale=1.0, tauk=1.0) + ComplexF64(0); scale=1.0, tauk=1.0) dp = ComplexF64[Q_a 0.0; 0.0 Q_b] mc = multi_surface_coupling([sc1, sc2], dp) amr_c = amr_scan(mc, (-1.0, 1.5), (-1.0, 1.0); - nre0=10, nim0=8, passes=4) + nre0=10, nim0=8, passes=4) r_c = find_growth_rates(amr_c, mc.surfaces[mc.ref_idx].tauk) @test abs(r_c.Q_root - Q_b) < 1e-2 # higher-γ root end @@ -175,15 +175,15 @@ # otherwise crosses the entire real axis). f(Q) = (ComplexF64(Q) - 0.0) / (ComplexF64(Q) - (-50.0)) + (1.0 + 1.0im) boxes = [((-75.0, -25.0), (-25.0, 25.0)), - ((-25.0, 25.0), (-25.0, 25.0)), - (( 25.0, 75.0), (-25.0, 25.0))] + ((-25.0, 25.0), (-25.0, 25.0)), + ((25.0, 75.0), (-25.0, 25.0))] result = multi_box_amr_scan(f, boxes; - pole_magnitude_threshold=10.0, - prescreen_nre=25, prescreen_nim=25, - nre0=25, nim0=25, passes=2, - max_cells=100_000, - max_cells_action=:warn_truncate, - parallel=false) + pole_magnitude_threshold=10.0, + prescreen_nre=25, prescreen_nim=25, + nre0=25, nim0=25, passes=2, + max_cells=100_000, + max_cells_action=:warn_truncate, + parallel=false) @test result isa MultiBoxAMRResult @test length(result.box_results) == 3 @test length(result.box_activity) == 3 @@ -212,15 +212,15 @@ # independent of sign-change tests. g(Q) = 1000.0 / (ComplexF64(Q) - (-50.0))^2 + (5.0 + 5.0im) boxes = [((-75.0, -25.0), (-25.0, 25.0)), - ((-25.0, 25.0), (-25.0, 25.0)), - (( 25.0, 75.0), (-25.0, 25.0))] + ((-25.0, 25.0), (-25.0, 25.0)), + ((25.0, 75.0), (-25.0, 25.0))] result = multi_box_amr_scan(g, boxes; - pole_magnitude_threshold=50.0, - prescreen_nre=25, prescreen_nim=25, - nre0=25, nim0=25, passes=1, - max_cells=100_000, - max_cells_action=:warn_truncate, - parallel=false) + pole_magnitude_threshold=50.0, + prescreen_nre=25, prescreen_nim=25, + nre0=25, nim0=25, passes=1, + max_cells=100_000, + max_cells_action=:warn_truncate, + parallel=false) @test result.box_activity[1] != NoActivity @test result.box_activity[2] == NoActivity @test result.box_activity[3] == NoActivity diff --git a/test/runtests_dispersion_coupled.jl b/test/runtests_dispersion_coupled.jl index 5a65539ff..d29745479 100644 --- a/test/runtests_dispersion_coupled.jl +++ b/test/runtests_dispersion_coupled.jl @@ -29,9 +29,9 @@ @testset "Constructor validation" begin sc1 = surface_coupling(LinTestModel(0.0im, 1.0+0im), nothing, - 1.0+0im; scale=1.0, tauk=1.0) + 1.0+0im; scale=1.0, tauk=1.0) sc2 = surface_coupling(LinTestModel(0.0im, 1.0+0im), nothing, - 2.0+0im; scale=1.0, tauk=1.0) + 2.0+0im; scale=1.0, tauk=1.0) good_dp = ComplexF64[1.0 0.1; 0.1 2.0] mc = multi_surface_coupling([sc1, sc2], good_dp) @@ -41,7 +41,7 @@ # 3-surface default also caps at 3 (min(3, 3) = 3) sc3 = surface_coupling(LinTestModel(0.0im, 1.0+0im), nothing, - 3.0+0im; scale=1.0, tauk=1.0) + 3.0+0im; scale=1.0, tauk=1.0) good_dp3 = ComplexF64[1.0 0.1 0.0; 0.1 2.0 0.0; 0.0 0.0 3.0] mc3 = multi_surface_coupling([sc1, sc2, sc3], good_dp3) @test mc3.msing_max == 3 @@ -49,16 +49,16 @@ # 4-surface case caps at 3 (the design default — Δ' beyond 3 surfaces # tends to be erratic in practice) sc4 = surface_coupling(LinTestModel(0.0im, 1.0+0im), nothing, - 4.0+0im; scale=1.0, tauk=1.0) + 4.0+0im; scale=1.0, tauk=1.0) good_dp4 = ComplexF64[1.0 0.0 0.0 0.0; - 0.0 2.0 0.0 0.0; - 0.0 0.0 3.0 0.0; - 0.0 0.0 0.0 4.0] + 0.0 2.0 0.0 0.0; + 0.0 0.0 3.0 0.0; + 0.0 0.0 0.0 4.0] mc4 = multi_surface_coupling([sc1, sc2, sc3, sc4], good_dp4) @test mc4.msing_max == 3 # default capped at 3 # Caller can opt in to all 4 mc4_full = multi_surface_coupling([sc1, sc2, sc3, sc4], good_dp4; - msing_max=4) + msing_max=4) @test mc4_full.msing_max == 4 # Mismatched dp size @@ -69,15 +69,15 @@ # Out-of-range ref_idx @test_throws ArgumentError multi_surface_coupling([sc1, sc2], good_dp; - ref_idx=3) + ref_idx=3) @test_throws ArgumentError multi_surface_coupling([sc1, sc2], good_dp; - ref_idx=0) + ref_idx=0) # Out-of-range msing_max @test_throws ArgumentError multi_surface_coupling([sc1, sc2], good_dp; - msing_max=3) + msing_max=3) @test_throws ArgumentError multi_surface_coupling([sc1, sc2], good_dp; - msing_max=0) + msing_max=0) end @testset "Diagonal Δ' factorizes (det = ∏ per-surface residuals)" begin @@ -85,14 +85,14 @@ # the coupled determinant should reduce exactly to the product of # per-surface residuals. sc1 = surface_coupling(LinTestModel(1.0+0im, 1.0+0im), nothing, - 5.0+0im; scale=1.0, tauk=1.0) + 5.0+0im; scale=1.0, tauk=1.0) sc2 = surface_coupling(LinTestModel(2.0+0im, 1.0+0im), nothing, - 7.0+0im; scale=1.0, tauk=1.0) + 7.0+0im; scale=1.0, tauk=1.0) sc3 = surface_coupling(LinTestModel(0.5+0im, 0.5+0im), nothing, - 3.0+0im; scale=1.0, tauk=1.0) + 3.0+0im; scale=1.0, tauk=1.0) dp = ComplexF64[5.0 0.0 0.0; - 0.0 7.0 0.0; - 0.0 0.0 3.0] + 0.0 7.0 0.0; + 0.0 0.0 3.0] mc = multi_surface_coupling([sc1, sc2, sc3], dp) for Q in (0.5+0im, 2.0+0.3im, -1.0-0.5im, 4.5+1.0im) @test mc(Q) ≈ sc1(Q) * sc2(Q) * sc3(Q) rtol = 1e-12 @@ -105,9 +105,9 @@ # single-surface roots. Q1, Q2 = 0.5+0.0im, 2.0+0.0im sc1 = surface_coupling(LinTestModel(0.0im, 1.0+0im), nothing, - Q1; scale=1.0, tauk=1.0) + Q1; scale=1.0, tauk=1.0) sc2 = surface_coupling(LinTestModel(0.0im, 1.0+0im), nothing, - Q2; scale=1.0, tauk=1.0) + Q2; scale=1.0, tauk=1.0) dp = ComplexF64[real(Q1) 0.0; 0.0 real(Q2)] mc = multi_surface_coupling([sc1, sc2], dp) @test abs(mc(Q1)) < 1e-12 @@ -117,9 +117,9 @@ @testset "Off-diagonal coupling shifts the roots away from the diagonal" begin sc1 = surface_coupling(LinTestModel(0.0im, 1.0+0im), nothing, - 0.5+0im; scale=1.0, tauk=1.0) + 0.5+0im; scale=1.0, tauk=1.0) sc2 = surface_coupling(LinTestModel(0.0im, 1.0+0im), nothing, - 2.0+0im; scale=1.0, tauk=1.0) + 2.0+0im; scale=1.0, tauk=1.0) # Coupling-free baseline dp_diag = ComplexF64[0.5 0.0; 0.0 2.0] mc_diag = multi_surface_coupling([sc1, sc2], dp_diag) @@ -138,14 +138,14 @@ @testset "msing_max truncation uses upper-left submatrix" begin sc1 = surface_coupling(LinTestModel(0.0im, 1.0+0im), nothing, - 1.0+0im; scale=1.0, tauk=1.0) + 1.0+0im; scale=1.0, tauk=1.0) sc2 = surface_coupling(LinTestModel(0.0im, 1.0+0im), nothing, - 2.0+0im; scale=1.0, tauk=1.0) + 2.0+0im; scale=1.0, tauk=1.0) sc3 = surface_coupling(LinTestModel(0.0im, 1.0+0im), nothing, - 3.0+0im; scale=1.0, tauk=1.0) + 3.0+0im; scale=1.0, tauk=1.0) dp = ComplexF64[1.0 0.0 0.0; - 0.0 2.0 0.0; - 0.0 0.0 3.0] + 0.0 2.0 0.0; + 0.0 0.0 3.0] # msing_max = 1 reduces to sc1(Q) alone mc1 = multi_surface_coupling([sc1, sc2, sc3], dp; msing_max=1) @@ -173,9 +173,9 @@ # M[k,k] = dp_diag_k - scale·Q·(tauk_ref/tauk_k) # Verify against an explicit closed form with mismatched tauks. sc1 = surface_coupling(LinTestModel(0.0im, 1.0+0im), nothing, - 0.0+0im; scale=1.0, tauk=2.0) # ref tauk + 0.0+0im; scale=1.0, tauk=2.0) # ref tauk sc2 = surface_coupling(LinTestModel(0.0im, 1.0+0im), nothing, - 0.0+0im; scale=1.0, tauk=4.0) # half rate + 0.0+0im; scale=1.0, tauk=4.0) # half rate dp = ComplexF64[0.0 0.0; 0.0 0.0] mc = multi_surface_coupling([sc1, sc2], dp; ref_idx=1) for Q in (1.0+0im, 0.5+0.3im) @@ -219,8 +219,8 @@ # Pick M[1,1] arbitrarily, solve for M[2,2]: M11 = 0.7 + 0.0im M22 = (c12 * c21) / M11 - dp = ComplexF64[M11+Δ1 c12; - c21 M22+Δ2] + dp = ComplexF64[M11+Δ1 c12; + c21 M22+Δ2] mc = multi_surface_coupling([sc1, sc2], dp) # The constructed M(Q_pin) is exactly singular by construction @@ -244,9 +244,9 @@ @testset "Broadcast over a 2D Q grid" begin # Coupled residual must be broadcast-compatible for PR 5/6 scans. sc1 = surface_coupling(LinTestModel(0.0im, 1.0+0im), nothing, - 0.0+0im; scale=1.0, tauk=1.0) + 0.0+0im; scale=1.0, tauk=1.0) sc2 = surface_coupling(LinTestModel(0.0im, 1.0+0im), nothing, - 0.0+0im; scale=1.0, tauk=1.0) + 0.0+0im; scale=1.0, tauk=1.0) dp = ComplexF64[0.0 0.0; 0.0 0.0] mc = multi_surface_coupling([sc1, sc2], dp) diff --git a/test/runtests_dispersion_coupled_full.jl b/test/runtests_dispersion_coupled_full.jl index d471650f8..65eec71c8 100644 --- a/test/runtests_dispersion_coupled_full.jl +++ b/test/runtests_dispersion_coupled_full.jl @@ -255,7 +255,7 @@ 0.2 0.1 0.05 0.1 0.3 -6.5] # Non-trivial Q dependence: Δ_t(Q) = a + 0.5·Q, Δ_i(Q) = b + 0.2·Q scs = [surface_coupling(_LinearInnerF(0.3 + 0.01k * im, 0.5 + 0im, - 0.7 + 0.02k * im, 0.2 + 0im), + 0.7 + 0.02k * im, 0.2 + 0im), nothing, 0 + 0im; scale=1.0, tauk=1.0) for k in 1:m] mc = multi_surface_coupling_full(scs, Random_dp) diff --git a/test/runtests_dispersion_polish.jl b/test/runtests_dispersion_polish.jl index 8bc4c9702..8e7ae2e7b 100644 --- a/test/runtests_dispersion_polish.jl +++ b/test/runtests_dispersion_polish.jl @@ -106,7 +106,7 @@ r1 = 0.30 + 0.20im r2 = r1 + 0.002 # second root 0.002 away f(Q) = (ComplexF64(Q) - r1) * (ComplexF64(Q) - r2) - pts = ComplexF64[r1 + 0.0003, r2 - 0.0003] # coarse contour estimates + pts = ComplexF64[r1+0.0003, r2-0.0003] # coarse contour estimates R1 = D._polish_trust_radius(pts, 1, 0.001) R2 = D._polish_trust_radius(pts, 2, 0.001) p1 = D._polish_root(f, pts[1], R1)[1] @@ -124,7 +124,7 @@ im_paths = [ComplexF64[0+0im, 0+0.1im]] # segment length 0.1 @test D._median_segment_length(re_paths, im_paths) ≈ 0.1 # median of [0.1,0.2,0.1] @test D._median_segment_length(Vector{Vector{ComplexF64}}(), - Vector{Vector{ComplexF64}}()) == 0.0 + Vector{Vector{ComplexF64}}()) == 0.0 end # ---------------------------------------------------------------- diff --git a/test/runtests_dispersion_residual.jl b/test/runtests_dispersion_residual.jl index d0235a0da..40cdbfd5d 100644 --- a/test/runtests_dispersion_residual.jl +++ b/test/runtests_dispersion_residual.jl @@ -30,35 +30,35 @@ @testset "Constructor scale defaults" begin # SLAYER: scale = lu^(1/3) so the dimensionless Δ from riccati_f # is mapped to outer ψ-units (Fortran SLAYER growthrates routine) - p_sl = _slayer_ref() + p_sl = _slayer_ref() sc_sl = surface_coupling(SLAYERModel(), p_sl, -1.0 + 0.0im) @test sc_sl.scale ≈ p_sl.lu^(1/3) @test sc_sl.dc == 0.0 @test sc_sl.dp_diag == ComplexF64(-1.0) # GGJ: scale = 1 because rescale_delta is applied inside solve_inner - p_ggj = glasser_wang_2020_eq55() + p_ggj = glasser_wang_2020_eq55() sc_ggj = surface_coupling(GGJModel(solver=:shooting), p_ggj, - -1.0 + 0.0im) + -1.0 + 0.0im) @test sc_ggj.scale == 1.0 # Generic fallback honors explicit scale + dc kwargs sc_lin = surface_coupling(LinearTestModel(0.0im, 1.0+0im), nothing, - 3.0 + 0.0im; dc=0.5, scale=2.0) + 3.0 + 0.0im; dc=0.5, scale=2.0) @test sc_lin.scale == 2.0 @test sc_lin.dc == 0.5 end @testset "Residual arithmetic on synthetic linear model" begin # r(Q) = dp_diag - scale·(a + b·Q) - dc - a, b = 1.0 + 2.0im, -0.5 + 1.0im - scale = 3.0 - dc = 0.25 + a, b = 1.0 + 2.0im, -0.5 + 1.0im + scale = 3.0 + dc = 0.25 Q_root = -0.7 + 0.3im dp_diag = (a + b * Q_root) * scale + dc # construct a known root sc = surface_coupling(LinearTestModel(a, b), nothing, dp_diag; - dc=dc, scale=scale) + dc=dc, scale=scale) @test sc(Q_root) ≈ 0 atol = 1e-12 # Off-root residual matches the closed form @@ -89,14 +89,14 @@ # Both inner-layer models flow through the same SurfaceCoupling # API. Numerical agreement is *not* asserted (different physics) — # only that both pipelines construct and evaluate. - p_sl = _slayer_ref() + p_sl = _slayer_ref() sc_sl = surface_coupling(SLAYERModel(), p_sl, -100.0 + 0.0im) @test sc_sl isa SurfaceCoupling{SLAYERModel{:fitzpatrick},SLAYERParameters} @test sc_sl(0.0 + 0.5im) isa ComplexF64 - p_ggj = glasser_wang_2020_eq55() + p_ggj = glasser_wang_2020_eq55() sc_ggj = surface_coupling(GGJModel(solver=:shooting), p_ggj, - -1.0 + 0.0im) + -1.0 + 0.0im) @test sc_ggj isa SurfaceCoupling{GGJModel{:shooting},GGJParameters} @test sc_ggj(1e-3 + 0.0im) isa ComplexF64 end @@ -106,7 +106,7 @@ # complex-Q grid; verify that broadcasting works element-wise. a, b = 0.0+0im, 1.0+0im sc = surface_coupling(LinearTestModel(a, b), nothing, 2.0+0im; - dc=0.0, scale=1.0) + dc=0.0, scale=1.0) Q_grid = [(qr + qi*im) for qr in -1.0:0.5:1.0, qi in -1.0:0.5:1.0] Δ_grid = sc.(Q_grid) @test size(Δ_grid) == size(Q_grid) diff --git a/test/runtests_dispersion_scan.jl b/test/runtests_dispersion_scan.jl index f50b449fc..00145ad63 100644 --- a/test/runtests_dispersion_scan.jl +++ b/test/runtests_dispersion_scan.jl @@ -7,16 +7,16 @@ @testset "brute_force_scan: regular grid evaluation" begin f(Q) = ComplexF64(Q)^2 - 1 scan = brute_force_scan(f, (-2.0, 2.0), (-1.0, 1.0); - nre=21, nim=11, threaded=false) + nre=21, nim=11, threaded=false) @test scan isa ScanResult @test size(scan.Q) == (21, 11) @test size(scan.Δ) == (21, 11) @test length(scan.re_axis) == 21 @test length(scan.im_axis) == 11 - @test scan.re_axis[1] == -2.0 - @test scan.re_axis[end] == 2.0 - @test scan.im_axis[1] == -1.0 - @test scan.im_axis[end] == 1.0 + @test scan.re_axis[1] == -2.0 + @test scan.re_axis[end] == 2.0 + @test scan.im_axis[1] == -1.0 + @test scan.im_axis[end] == 1.0 # Spot-check a grid value i, j = 11, 6 @test scan.Q[i, j] ≈ scan.re_axis[i] + scan.im_axis[j]*im @@ -26,17 +26,17 @@ @testset "brute_force_scan: threaded vs non-threaded agree" begin f(Q) = sin(ComplexF64(Q)) s_t = brute_force_scan(f, (-1.0, 1.0), (-0.5, 0.5); - nre=15, nim=10, threaded=true) + nre=15, nim=10, threaded=true) s_n = brute_force_scan(f, (-1.0, 1.0), (-0.5, 0.5); - nre=15, nim=10, threaded=false) + nre=15, nim=10, threaded=false) @test s_t.Δ == s_n.Δ end @testset "brute_force_scan: argument validation" begin @test_throws ArgumentError brute_force_scan(identity, (0.0, 1.0), - (0.0, 1.0); nre=1, nim=10) + (0.0, 1.0); nre=1, nim=10) @test_throws ArgumentError brute_force_scan(identity, (0.0, 1.0), - (0.0, 1.0); nre=10, nim=1) + (0.0, 1.0); nre=10, nim=1) end @testset "find_growth_rates: single isolated root" begin @@ -44,7 +44,7 @@ Q_root = 0.42 + 0.27im f(Q) = ComplexF64(Q) - Q_root scan = brute_force_scan(f, (-1.0, 1.5), (-0.5, 1.0); - nre=80, nim=60, threaded=false) + nre=80, nim=60, threaded=false) result = find_growth_rates(scan, 1.0) @test result isa GrowthRateResult @test isempty(result.poles) @@ -60,7 +60,7 @@ Q2 = -0.4 + 0.1im # lower γ f(Q) = (ComplexF64(Q) - Q1) * (ComplexF64(Q) - Q2) scan = brute_force_scan(f, (-1.0, 1.0), (-0.3, 0.8); - nre=100, nim=80, threaded=false) + nre=100, nim=80, threaded=false) result = find_growth_rates(scan, 1.0) @test length(result.valid_roots) == 2 @test abs(result.Q_root - Q1) < 1e-3 # higher-γ root chosen @@ -73,7 +73,7 @@ Q_p = -0.5 + 0.6im # pole at higher γ f(Q) = (ComplexF64(Q) - Q_r) / (ComplexF64(Q) - Q_p) scan = brute_force_scan(f, (-1.5, 1.5), (-0.5, 1.5); - nre=120, nim=100, threaded=false) + nre=120, nim=100, threaded=false) result = find_growth_rates(scan, 1.0; pole_threshold=10.0) # Pole correctly classified — but the root is at lower γ than the # pole, so even with filter_above_poles=true the root must survive. @@ -86,14 +86,14 @@ Q_root = 1.0 + 2.0im f(Q) = ComplexF64(Q) - Q_root scan = brute_force_scan(f, (-2.0, 3.0), (-1.0, 4.0); - nre=80, nim=80, threaded=false) + nre=80, nim=80, threaded=false) tauk = 5.0e-5 result = find_growth_rates(scan, tauk) @test result.omega_Hz ≈ real(result.Q_root) / tauk @test result.gamma_Hz ≈ imag(result.Q_root) / tauk # Check sensible orders of magnitude (Q_root ≈ 1+2im, tauk ≈ 5e-5) - @test result.omega_Hz ≈ 1 / tauk atol = 1 / tauk * 5e-3 - @test result.gamma_Hz ≈ 2 / tauk atol = 2 / tauk * 5e-3 + @test result.omega_Hz ≈ 1 / tauk atol = 1 / tauk * 5e-3 + @test result.gamma_Hz ≈ 2 / tauk atol = 2 / tauk * 5e-3 end @testset "find_growth_rates: empty result when no contour intersections" begin @@ -102,7 +102,7 @@ f(Q) = 1.0 + ComplexF64(Q) # Choose a box where Δ has no zeros — far above the real axis scan = brute_force_scan(f, (1.0, 2.0), (1.0, 2.0); - nre=30, nim=30, threaded=false) + nre=30, nim=30, threaded=false) result = find_growth_rates(scan, 1.0) # Either no valid roots, or a NaN Q_root @test isempty(result.valid_roots) || isnan(real(result.Q_root)) @@ -122,9 +122,9 @@ # Single-surface scan via SurfaceCoupling (Q_root by construction = 0.7-0.3im) Q_pin = 0.7 - 0.3im sc = surface_coupling(LinModel(0.0im, 1.0+0im), nothing, - Q_pin; scale=1.0, tauk=1.0) + Q_pin; scale=1.0, tauk=1.0) scan = brute_force_scan(sc, (-0.5, 1.5), (-1.0, 0.5); - nre=80, nim=80, threaded=false) + nre=80, nim=80, threaded=false) res = find_growth_rates(scan, sc.tauk) @test abs(res.Q_root - Q_pin) < 1e-3 @@ -136,13 +136,13 @@ # full complex value, not just its real part). Q_a, Q_b = 0.7 - 0.3im, -0.4 + 0.5im sc1 = surface_coupling(LinModel(0.0im, 1.0+0im), nothing, - ComplexF64(0); scale=1.0, tauk=1.0) + ComplexF64(0); scale=1.0, tauk=1.0) sc2 = surface_coupling(LinModel(0.0im, 1.0+0im), nothing, - ComplexF64(0); scale=1.0, tauk=1.0) + ComplexF64(0); scale=1.0, tauk=1.0) dp = ComplexF64[Q_a 0.0; 0.0 Q_b] # diagonal Δ' mc = multi_surface_coupling([sc1, sc2], dp) scan_c = brute_force_scan(mc, (-1.0, 1.5), (-1.0, 1.0); - nre=120, nim=100, threaded=false) + nre=120, nim=100, threaded=false) res_c = find_growth_rates(scan_c, mc.surfaces[mc.ref_idx].tauk) # With diagonal Δ', det = (Q_a - Q)·(Q_b - Q) → roots at Q_a, Q_b. # The higher-γ root is Q_b (γ = 0.5). diff --git a/test/runtests_equil.jl b/test/runtests_equil.jl index af3cd5743..782ae6120 100644 --- a/test/runtests_equil.jl +++ b/test/runtests_equil.jl @@ -143,7 +143,7 @@ @testset "EFIT Method Consistency" begin # All three methods solve the same equilibrium — q-profiles should broadly agree. # Tolerance is 10% to allow for method-specific discretisation differences. - q_efit = plasma_eq_efit.profiles.q_spline.y + q_efit = plasma_eq_efit.profiles.q_spline.y q_arclength = plasma_eq_arclength.profiles.q_spline.y q_inversion = plasma_eq_inversion.profiles.q_spline.y @@ -242,7 +242,7 @@ b0exp = 7.4 # CHEASE normalization field [T] B_nodes_binary = plasma_eq_binary.eqfun_B.nodal_derivs.partials[1, :, :] - B_nodes_ascii = plasma_eq_ascii.eqfun_B.nodal_derivs.partials[1, :, :] + B_nodes_ascii = plasma_eq_ascii.eqfun_B.nodal_derivs.partials[1, :, :] # B field must be finite and positive everywhere @test all(isfinite, B_nodes_binary) @@ -258,7 +258,7 @@ # q must be finite, positive, and in a physically reasonable range q_binary = plasma_eq_binary.profiles.q_spline.y - q_ascii = plasma_eq_ascii.profiles.q_spline.y + q_ascii = plasma_eq_ascii.profiles.q_spline.y @test all(isfinite, q_binary) @test all(isfinite, q_ascii) @test all(>(0), q_binary) @@ -436,7 +436,7 @@ Eq = GeneralizedPerturbedEquilibrium.Equilibrium function build_solovev_equilibrium(; e=1.6, a=0.33, r0=1.0, q0=1.9, - mpsi=64, mtheta=128) + mpsi=64, mtheta=128) eq_config = Eq.EquilibriumConfig(; eq_type="sol", eq_filename="unused", jac_type="pest", grid_type="ldp", @@ -515,24 +515,24 @@ @test pe.params.zsep[1] > pe.params.zsep[2] # Shape parameters — all physically positive quantities. - @test pe.params.amean > 0 - @test pe.params.rmean > 0 + @test pe.params.amean > 0 + @test pe.params.rmean > 0 @test pe.params.aratio > 0 - @test pe.params.kappa > 0 - @test pe.params.kappa ≈ 1.6 rtol=0.02 + @test pe.params.kappa > 0 + @test pe.params.kappa ≈ 1.6 rtol=0.02 # For Solovev (e=1.6, a=0.33, r0=1.0) the shape is approximately # recovered (Shafranov shift loosens the match). @test pe.params.amean ≈ 0.33 rtol=0.15 - @test pe.params.rmean ≈ 1.0 rtol=0.15 + @test pe.params.rmean ≈ 1.0 rtol=0.15 # Consistency with separatrix formulae. @test pe.params.rmean ≈ (pe.params.rsep[1] + pe.params.rsep[2]) / 2 @test pe.params.amean ≈ (pe.params.rsep[1] - pe.params.rsep[2]) / 2 # Beta and field quantities — all physically positive. - @test pe.params.bt0 > 0 - @test pe.params.crnt > 0 + @test pe.params.bt0 > 0 + @test pe.params.crnt > 0 @test pe.params.bwall > 0 @test pe.params.betat > 0 @test pe.params.betan > 0 diff --git a/test/runtests_eulerlagrange.jl b/test/runtests_eulerlagrange.jl index 6547352e6..6794ec296 100644 --- a/test/runtests_eulerlagrange.jl +++ b/test/runtests_eulerlagrange.jl @@ -494,7 +494,7 @@ end # materialize after the Gaussian fixups and free-boundary normalization rather than # transforming stored derivatives alongside u_store. npert = intr.numpert_total - T = Matrix{ComplexF64}(I, npert, npert) .+ 0.25 .* ComplexF64.(reshape(sin.(1:npert^2), npert, npert)) + T = Matrix{ComplexF64}(I, npert, npert) .+ 0.25 .* ComplexF64.(reshape(sin.(1:(npert^2)), npert, npert)) odet_t = deepcopy(odet_pristine) for istep in 1:odet_t.step odet_t.u_store[:, :, 1, istep] = odet_t.u_store[:, :, 1, istep] * T diff --git a/test/runtests_imas.jl b/test/runtests_imas.jl index 2d82d5b0e..f261cc45a 100644 --- a/test/runtests_imas.jl +++ b/test/runtests_imas.jl @@ -20,31 +20,31 @@ using GeneralizedPerturbedEquilibrium.Equilibrium # COCOS 11: ψ_IMAS = 2π × ψ_internal psi_axis_int = 0.0 - psi_bnd_int = 1.5 # Wb/rad + psi_bnd_int = 1.5 # Wb/rad cf = cocos == 11 ? 2π : 1.0 - eqt.global_quantities.psi_axis = psi_axis_int * cf - eqt.global_quantities.psi_boundary = psi_bnd_int * cf + eqt.global_quantities.psi_axis = psi_axis_int * cf + eqt.global_quantities.psi_boundary = psi_bnd_int * cf nw = 64 psi_1d = collect(LinRange(psi_axis_int, psi_bnd_int, nw)) - eqt.profiles_1d.psi = psi_1d .* cf - eqt.profiles_1d.f = fill(5.0, nw) + eqt.profiles_1d.psi = psi_1d .* cf + eqt.profiles_1d.f = fill(5.0, nw) eqt.profiles_1d.pressure = collect(LinRange(1e4, 0.0, nw)) - eqt.profiles_1d.q = collect(LinRange(1.0, 3.0, nw)) + eqt.profiles_1d.q = collect(LinRange(1.0, 3.0, nw)) # Minimal 2D ψ(R,Z) — rough circular flux surfaces nR, nZ = 32, 40 R_grid = collect(LinRange(1.0, 2.5, nR)) Z_grid = collect(LinRange(-0.8, 0.8, nZ)) - Rmag = 1.75 + Rmag = 1.75 psi_rz = [min((R - Rmag)^2 / 0.6 + Z^2 / 0.7, psi_bnd_int * 1.4) for R in R_grid, Z in Z_grid] resize!(eqt.profiles_2d, 1; wipe=true) - prof2d = eqt.profiles_2d[1] - prof2d.grid.dim1 = R_grid - prof2d.grid.dim2 = Z_grid - prof2d.psi = psi_rz .* cf + prof2d = eqt.profiles_2d[1] + prof2d.grid.dim1 = R_grid + prof2d.grid.dim2 = Z_grid + prof2d.psi = psi_rz .* cf return dd, psi_bnd_int end @@ -58,8 +58,8 @@ using GeneralizedPerturbedEquilibrium.Equilibrium # psio should equal |psi_boundary - psi_axis| in internal (COCOS 2) units @test isapprox(result.psio, psi_bnd_int; rtol=1e-6) - @test result.rmin ≈ 1.0 atol=1e-9 - @test result.rmax ≈ 2.5 atol=1e-9 + @test result.rmin ≈ 1.0 atol=1e-9 + @test result.rmax ≈ 2.5 atol=1e-9 end # Test 2: read_imas — COCOS 2 input requires no conversion @@ -121,7 +121,7 @@ using GeneralizedPerturbedEquilibrium.Equilibrium GeneralizedPerturbedEquilibrium.write_imas(dd, mock_result) - @test dd.mhd_linear.code.name == "GPEC" + @test dd.mhd_linear.code.name == "GPEC" @test dd.mhd_linear.ideal_flag == 1 @test length(dd.mhd_linear.time_slice) == 1 @@ -142,7 +142,7 @@ using GeneralizedPerturbedEquilibrium.Equilibrium # et sorted ascending (least stable globally first). # n=1 (j=0) has eigenvalues: real=0.3 (idx 1) and real=0.6 (idx 3) # n=2 (j=1) has eigenvalues: real=0.5 (idx 2) and real=0.7 (idx 4) - mock_et = [0.3+0im, 0.5+0im, 0.6+0im, 0.7+0im] + mock_et = [0.3+0im, 0.5+0im, 0.6+0im, 0.7+0im] mock_n_idx = [0, 1, 0, 1] mock_result = ( ffs = (integrator=:forward, free_boundary=(et=mock_et, n_tor_idx=mock_n_idx), @@ -190,9 +190,9 @@ using GeneralizedPerturbedEquilibrium.Equilibrium ) GeneralizedPerturbedEquilibrium.write_imas(dd_multi, result_multi) - ts_single = dd_single.mhd_linear.time_slice[1] + ts_single = dd_single.mhd_linear.time_slice[1] ts_single2 = dd_single2.mhd_linear.time_slice[1] - ts_multi = dd_multi.mhd_linear.time_slice[1] + ts_multi = dd_multi.mhd_linear.time_slice[1] # n=1 energy from combined run must match the standalone n=1 run @test ts_multi.toroidal_mode[1].energy_perturbed == ts_single.toroidal_mode[1].energy_perturbed diff --git a/test/runtests_kinetic.jl b/test/runtests_kinetic.jl index 29955c2c7..7f1ac8fcf 100644 --- a/test/runtests_kinetic.jl +++ b/test/runtests_kinetic.jl @@ -26,7 +26,7 @@ @testset "endpoint modes" begin pts_lower, _ = KF.powspace(0.0, 1.0, 2, 50, "lower") pts_upper, _ = KF.powspace(0.0, 1.0, 2, 50, "upper") - pts_both, _ = KF.powspace(0.0, 1.0, 2, 50, "both") + pts_both, _ = KF.powspace(0.0, 1.0, 2, 50, "both") # All modes should span the full range for pts in [pts_lower, pts_upper, pts_both] @@ -194,11 +194,11 @@ # independent reference for the u-substitution + pole-extraction result. wn, wt, we, wd, wb, nuk, leff, n = 0.5, 0.8, -2.0, 0.5, 1.0, 0.3, 1.0, 1 p = KF.EnergyParams(wn, wt, we, wd, wb, nuk, leff, n, - "harmonic", "maxwellian", 1.0, 0.0, false) + "harmonic", "maxwellian", 1.0, 0.0, false) x_res = KF.find_resonance_energies(leff, wb, n, we, wd) @test length(x_res) == 1 # this case has exactly one resonance reference, _ = KF.quadgk(x -> KF.energy_integrand_scalar(x, p), - 0.0, x_res[1], Inf; rtol=1e-12, atol=1e-14) + 0.0, x_res[1], Inf; rtol=1e-12, atol=1e-14) result = KF.integrate_energy( wn, wt, we, wd, wb, nuk, 0, leff, n, 0.5, 0.5, "fgar"; nutype="harmonic", f0type="maxwellian", atol=1e-12, rtol=1e-10 @@ -317,7 +317,7 @@ @test all(isfinite, vals) # Element-wise match against the scalar form documented in the docstring. p = KF.EnergyParams(0.5, 0.8, -2.0, 0.5, 1.0, 0.3, 1.0, 1, - "harmonic", "maxwellian", 1.0, 0.0, false) + "harmonic", "maxwellian", 1.0, 0.0, false) @test vals ≈ [KF.energy_integrand_scalar(x, p) for x in x_grid] end diff --git a/test/runtests_parallel_integration.jl b/test/runtests_parallel_integration.jl index 7e7737e06..616cc28d6 100644 --- a/test/runtests_parallel_integration.jl +++ b/test/runtests_parallel_integration.jl @@ -114,9 +114,12 @@ using TOML ctrl = GeneralizedPerturbedEquilibrium.ForceFreeStates.ForceFreeStatesControl(; (Symbol(k) => v for (k, v) in inputs["ForceFreeStates"])...) eq_config = GeneralizedPerturbedEquilibrium.Equilibrium.EquilibriumConfig(inputs["Equilibrium"], ex) - equil = GeneralizedPerturbedEquilibrium.Equilibrium.setup_equilibrium(eq_config, haskey(inputs, "SOL_INPUT") ? GeneralizedPerturbedEquilibrium.Equilibrium.SolovevConfig(inputs["SOL_INPUT"]) : nothing) - intr.nlow = ctrl.nn_low; - intr.nhigh = ctrl.nn_high; + equil = GeneralizedPerturbedEquilibrium.Equilibrium.setup_equilibrium( + eq_config, + haskey(inputs, "SOL_INPUT") ? GeneralizedPerturbedEquilibrium.Equilibrium.SolovevConfig(inputs["SOL_INPUT"]) : nothing + ) + intr.nlow = ctrl.nn_low + intr.nhigh = ctrl.nn_high intr.npert = 1 GeneralizedPerturbedEquilibrium.ForceFreeStates.sing_lim!(intr, ctrl, equil) GeneralizedPerturbedEquilibrium.ForceFreeStates.sing_find!(intr, equil) @@ -201,9 +204,12 @@ using TOML ctrl = GeneralizedPerturbedEquilibrium.ForceFreeStates.ForceFreeStatesControl(; (Symbol(k) => v for (k, v) in inputs["ForceFreeStates"])...) eq_config = GeneralizedPerturbedEquilibrium.Equilibrium.EquilibriumConfig(inputs["Equilibrium"], ex) - equil = GeneralizedPerturbedEquilibrium.Equilibrium.setup_equilibrium(eq_config, haskey(inputs, "SOL_INPUT") ? GeneralizedPerturbedEquilibrium.Equilibrium.SolovevConfig(inputs["SOL_INPUT"]) : nothing) - intr.nlow = ctrl.nn_low; - intr.nhigh = ctrl.nn_high; + equil = GeneralizedPerturbedEquilibrium.Equilibrium.setup_equilibrium( + eq_config, + haskey(inputs, "SOL_INPUT") ? GeneralizedPerturbedEquilibrium.Equilibrium.SolovevConfig(inputs["SOL_INPUT"]) : nothing + ) + intr.nlow = ctrl.nn_low + intr.nhigh = ctrl.nn_high intr.npert = 1 GeneralizedPerturbedEquilibrium.ForceFreeStates.sing_lim!(intr, ctrl, equil) GeneralizedPerturbedEquilibrium.ForceFreeStates.sing_find!(intr, equil) @@ -262,11 +268,14 @@ using TOML ctrl = GeneralizedPerturbedEquilibrium.ForceFreeStates.ForceFreeStatesControl(; (Symbol(k) => v for (k, v) in inputs["ForceFreeStates"])...) eq_config = GeneralizedPerturbedEquilibrium.Equilibrium.EquilibriumConfig(inputs["Equilibrium"], ex) - equil = GeneralizedPerturbedEquilibrium.Equilibrium.setup_equilibrium(eq_config, haskey(inputs, "SOL_INPUT") ? GeneralizedPerturbedEquilibrium.Equilibrium.SolovevConfig(inputs["SOL_INPUT"]) : nothing) + equil = GeneralizedPerturbedEquilibrium.Equilibrium.setup_equilibrium( + eq_config, + haskey(inputs, "SOL_INPUT") ? GeneralizedPerturbedEquilibrium.Equilibrium.SolovevConfig(inputs["SOL_INPUT"]) : nothing + ) intr.wall_settings = GeneralizedPerturbedEquilibrium.Vacuum.WallShapeSettings(; (Symbol(k) => v for (k, v) in inputs["Wall"])...) - intr.nlow = ctrl.nn_low; - intr.nhigh = ctrl.nn_high; + intr.nlow = ctrl.nn_low + intr.nhigh = ctrl.nn_high intr.npert = 1 GeneralizedPerturbedEquilibrium.ForceFreeStates.sing_lim!(intr, ctrl, equil) GeneralizedPerturbedEquilibrium.ForceFreeStates.sing_find!(intr, equil) @@ -311,7 +320,10 @@ using TOML ctrl = GeneralizedPerturbedEquilibrium.ForceFreeStates.ForceFreeStatesControl(; (Symbol(k) => v for (k, v) in inputs["ForceFreeStates"])...) eq_config = GeneralizedPerturbedEquilibrium.Equilibrium.EquilibriumConfig(inputs["Equilibrium"], ex) - equil = GeneralizedPerturbedEquilibrium.Equilibrium.setup_equilibrium(eq_config, haskey(inputs, "SOL_INPUT") ? GeneralizedPerturbedEquilibrium.Equilibrium.SolovevConfig(inputs["SOL_INPUT"]) : nothing) + equil = GeneralizedPerturbedEquilibrium.Equilibrium.setup_equilibrium( + eq_config, + haskey(inputs, "SOL_INPUT") ? GeneralizedPerturbedEquilibrium.Equilibrium.SolovevConfig(inputs["SOL_INPUT"]) : nothing + ) # Apply the two-pass auto grid exactly as the main driver does (the example ships # grid_type="auto", mpsi=0): measured-curvature refinement with rational surfaces # pinned as mandatory knots, re-formed from the captured ingest. The pinned values @@ -324,8 +336,8 @@ using TOML end intr.wall_settings = GeneralizedPerturbedEquilibrium.Vacuum.WallShapeSettings(; (Symbol(k) => v for (k, v) in inputs["Wall"])...) - intr.nlow = ctrl.nn_low; - intr.nhigh = ctrl.nn_high; + intr.nlow = ctrl.nn_low + intr.nhigh = ctrl.nn_high intr.npert = 1 GeneralizedPerturbedEquilibrium.ForceFreeStates.sing_lim!(intr, ctrl, equil) GeneralizedPerturbedEquilibrium.ForceFreeStates.sing_find!(intr, equil) @@ -372,9 +384,12 @@ using TOML ctrl = GeneralizedPerturbedEquilibrium.ForceFreeStates.ForceFreeStatesControl(; (Symbol(k) => v for (k, v) in inputs["ForceFreeStates"])...) eq_config = GeneralizedPerturbedEquilibrium.Equilibrium.EquilibriumConfig(inputs["Equilibrium"], ex) - equil = GeneralizedPerturbedEquilibrium.Equilibrium.setup_equilibrium(eq_config, haskey(inputs, "SOL_INPUT") ? GeneralizedPerturbedEquilibrium.Equilibrium.SolovevConfig(inputs["SOL_INPUT"]) : nothing) - intr.nlow = ctrl.nn_low; - intr.nhigh = ctrl.nn_high; + equil = GeneralizedPerturbedEquilibrium.Equilibrium.setup_equilibrium( + eq_config, + haskey(inputs, "SOL_INPUT") ? GeneralizedPerturbedEquilibrium.Equilibrium.SolovevConfig(inputs["SOL_INPUT"]) : nothing + ) + intr.nlow = ctrl.nn_low + intr.nhigh = ctrl.nn_high intr.npert = 1 GeneralizedPerturbedEquilibrium.ForceFreeStates.sing_lim!(intr, ctrl, equil) GeneralizedPerturbedEquilibrium.ForceFreeStates.sing_find!(intr, equil) @@ -423,11 +438,14 @@ using TOML ctrl = GeneralizedPerturbedEquilibrium.ForceFreeStates.ForceFreeStatesControl(; (Symbol(k) => v for (k, v) in inputs["ForceFreeStates"])...) eq_config = GeneralizedPerturbedEquilibrium.Equilibrium.EquilibriumConfig(inputs["Equilibrium"], example_dir) - equil = GeneralizedPerturbedEquilibrium.Equilibrium.setup_equilibrium(eq_config, haskey(inputs, "SOL_INPUT") ? GeneralizedPerturbedEquilibrium.Equilibrium.SolovevConfig(inputs["SOL_INPUT"]) : nothing) + equil = GeneralizedPerturbedEquilibrium.Equilibrium.setup_equilibrium( + eq_config, + haskey(inputs, "SOL_INPUT") ? GeneralizedPerturbedEquilibrium.Equilibrium.SolovevConfig(inputs["SOL_INPUT"]) : nothing + ) intr.wall_settings = GeneralizedPerturbedEquilibrium.Vacuum.WallShapeSettings(; (Symbol(k) => v for (k, v) in inputs["Wall"])...) - intr.nlow = ctrl.nn_low; - intr.nhigh = ctrl.nn_high; + intr.nlow = ctrl.nn_low + intr.nhigh = ctrl.nn_high intr.npert = 1 GeneralizedPerturbedEquilibrium.ForceFreeStates.sing_lim!(intr, ctrl, equil) GeneralizedPerturbedEquilibrium.ForceFreeStates.sing_find!(intr, equil) @@ -476,7 +494,10 @@ using TOML ctrl = GeneralizedPerturbedEquilibrium.ForceFreeStates.ForceFreeStatesControl(; (Symbol(k) => v for (k, v) in inputs["ForceFreeStates"])...) eq_config = GeneralizedPerturbedEquilibrium.Equilibrium.EquilibriumConfig(inputs["Equilibrium"], ex) - equil = GeneralizedPerturbedEquilibrium.Equilibrium.setup_equilibrium(eq_config, haskey(inputs, "SOL_INPUT") ? GeneralizedPerturbedEquilibrium.Equilibrium.SolovevConfig(inputs["SOL_INPUT"]) : nothing) + equil = GeneralizedPerturbedEquilibrium.Equilibrium.setup_equilibrium( + eq_config, + haskey(inputs, "SOL_INPUT") ? GeneralizedPerturbedEquilibrium.Equilibrium.SolovevConfig(inputs["SOL_INPUT"]) : nothing + ) # Apply the two-pass auto grid (measured-curvature refinement, rational surfaces pinned # as mandatory knots) exactly as the main driver does (see the FM testset above); the # pinned values below are for this grid, the production default. @@ -488,8 +509,8 @@ using TOML end intr.wall_settings = GeneralizedPerturbedEquilibrium.Vacuum.WallShapeSettings(; (Symbol(k) => v for (k, v) in inputs["Wall"])...) - intr.nlow = ctrl.nn_low; - intr.nhigh = ctrl.nn_high; + intr.nlow = ctrl.nn_low + intr.nhigh = ctrl.nn_high intr.npert = 1 GeneralizedPerturbedEquilibrium.ForceFreeStates.sing_lim!(intr, ctrl, equil) GeneralizedPerturbedEquilibrium.ForceFreeStates.sing_find!(intr, equil) diff --git a/test/runtests_rerun_from_h5.jl b/test/runtests_rerun_from_h5.jl index dc242426f..db10e3c9d 100644 --- a/test/runtests_rerun_from_h5.jl +++ b/test/runtests_rerun_from_h5.jl @@ -102,7 +102,11 @@ end inputs, = GeneralizedPerturbedEquilibrium.build_inputs_from_h5([source_h5, "--output-dir", out_dir, "--override", "ForceFreeStates.use_parallel=true"]) @test inputs["ForceFreeStates"]["use_parallel"] == true - @test_logs (:warn,) GeneralizedPerturbedEquilibrium._drop_deprecated_keys!(inputs["ForceFreeStates"], GeneralizedPerturbedEquilibrium._DEPRECATED_FFS_KEYS, "ForceFreeStates") + @test_logs (:warn,) GeneralizedPerturbedEquilibrium._drop_deprecated_keys!( + inputs["ForceFreeStates"], + GeneralizedPerturbedEquilibrium._DEPRECATED_FFS_KEYS, + "ForceFreeStates" + ) @test !haskey(inputs["ForceFreeStates"], "use_parallel") # With the key gone the control struct builds again, on the default integrator. diff --git a/test/runtests_riccati.jl b/test/runtests_riccati.jl index afd084056..69edfb972 100644 --- a/test/runtests_riccati.jl +++ b/test/runtests_riccati.jl @@ -9,8 +9,8 @@ function make_solovev_intr(inputs, ctrl, equil, ex) intr = FFS.ForceFreeStatesInternal(; dir_path=ex) intr.wall_settings = GeneralizedPerturbedEquilibrium.Vacuum.WallShapeSettings(; (Symbol(k) => v for (k, v) in inputs["Wall"])...) - intr.nlow = ctrl.nn_low; - intr.nhigh = ctrl.nn_high; + intr.nlow = ctrl.nn_low + intr.nhigh = ctrl.nn_high intr.npert = 1 FFS.sing_lim!(intr, ctrl, equil) FFS.sing_find!(intr, equil) diff --git a/test/runtests_sing.jl b/test/runtests_sing.jl index 83b85a765..18ce06c59 100644 --- a/test/runtests_sing.jl +++ b/test/runtests_sing.jl @@ -41,14 +41,14 @@ using FastInterpolations: cubic_interp, CubicFit, LinearBinarySearch, Series, Ex function read_solutions_3d(fname::String) lines = readlines(fname) - blocks = Vector{Vector{Vector{Float64}}}(); + blocks = Vector{Vector{Vector{Float64}}}() current = Vector{Vector{Float64}}() for s in lines - t = strip(s); + t = strip(s) isempty(t) && continue if occursin("Solution index", t) if !isempty(current) - push!(blocks, current); + push!(blocks, current) current = Vector{Vector{Float64}}() end continue @@ -62,11 +62,11 @@ using FastInterpolations: cubic_interp, CubicFit, LinearBinarySearch, Series, Ex if !isempty(current) push!(blocks, current) end - mpert = length(blocks[1]); + mpert = length(blocks[1]) nsol = length(blocks) result = Array{ComplexF64}(undef, mpert, nsol, 2) for (j, block) in enumerate(blocks), (i, row) in enumerate(block) - result[i, j, 1] = complex(row[2], row[3]); + result[i, j, 1] = complex(row[2], row[3]) result[i, j, 2] = complex(row[4], row[5]) end return result @@ -105,7 +105,7 @@ using FastInterpolations: cubic_interp, CubicFit, LinearBinarySearch, Series, Ex odet = GeneralizedPerturbedEquilibrium.ForceFreeStates.OdeState(; numpert_total=intr.numpert_total, numsteps_init=ctrl.numsteps_init, numunorms_init=ctrl.numunorms_init, msing=intr.msing) - psifac_dummy = collect(range(0, 1, 10)); + psifac_dummy = collect(range(0, 1, 10)) points = length(psifac_dummy) amat = read_complex_fortran(joinpath(@__DIR__, "test_data/sing_der_testing/mat_dat/amat.dat")) amats = copyForSplines(amat, psifac_dummy) @@ -115,7 +115,7 @@ using FastInterpolations: cubic_interp, CubicFit, LinearBinarySearch, Series, Ex cmats = copyForSplines(cmat, psifac_dummy) fmat = read_complex_fortran(joinpath(@__DIR__, "test_data/sing_der_testing/mat_dat/fmat.dat")) - fmat .= cholesky(Hermitian(fmat)).L; + fmat .= cholesky(Hermitian(fmat)).L fmats = copyForSplines(fmat, psifac_dummy) kmat = read_complex_fortran(joinpath(@__DIR__, "test_data/sing_der_testing/mat_dat/kmat.dat")) kmats = copyForSplines(kmat, psifac_dummy) @@ -125,7 +125,7 @@ using FastInterpolations: cubic_interp, CubicFit, LinearBinarySearch, Series, Ex umat_p1 = read_complex_fortran(joinpath(@__DIR__, "test_data/sing_der_testing/mat_dat/umat_p1.dat")) umat_p2 = read_complex_fortran(joinpath(@__DIR__, "test_data/sing_der_testing/mat_dat/umat_p2.dat")) odet.psifac = extract_value(joinpath(@__DIR__, "test_data/sing_der_testing/mat_dat/sing_der_output_normal.dat"), "psifac") - odet.u[:, :, 1] .= umat_p1; + odet.u[:, :, 1] .= umat_p1 odet.u[:, :, 2] .= umat_p2 ffit = GeneralizedPerturbedEquilibrium.ForceFreeStates.FourFitVars(; mpert=intr.numpert_total, numpert_total=intr.numpert_total) diff --git a/test/runtests_tj_analytic.jl b/test/runtests_tj_analytic.jl index 5bbcb25d2..b36702001 100644 --- a/test/runtests_tj_analytic.jl +++ b/test/runtests_tj_analytic.jl @@ -19,12 +19,12 @@ using GeneralizedPerturbedEquilibrium.Equilibrium: TJAnalyticConfig, Equilibrium @testset "TJ-analytic model" begin @testset "tj_analytic_run (inverse) — basic invariants at ε = 0.25" begin # Keep ε, mpsi, mtheta modest so the whole block runs in ~1 s. - tj = TJAnalyticConfig(lar_r0 = 1.0 / 0.25, lar_a = 1.0, - qc = 1.5, qa = 3.6, pc = 0.001, mu = 2.0, B0 = 12.0, - ma = 64, mtau = 64) - eq = EquilibriumConfig(eq_type = "tj_analytic", - psilow = 0.01, psihigh = 0.995, - mpsi = 64, mtheta = 128, etol = 1e-7) + tj = TJAnalyticConfig(lar_r0=1.0 / 0.25, lar_a=1.0, + qc=1.5, qa=3.6, pc=0.001, mu=2.0, B0=12.0, + ma=64, mtau=64) + eq = EquilibriumConfig(eq_type="tj_analytic", + psilow=0.01, psihigh=0.995, + mpsi=64, mtheta=128, etol=1e-7) pe = setup_equilibrium(eq, tj) # psio is a physical-scale ψ; regressions in the a→a² normalization @@ -33,12 +33,12 @@ using GeneralizedPerturbedEquilibrium.Equilibrium: TJAnalyticConfig, Equilibrium @test isfinite(pe.psio) # ν root-find pins q₂(x=1) = qa; qmax at psihigh=0.995 lands ~0.04 below. - @test pe.params.q0 ≈ 1.5 rtol = 1e-3 + @test pe.params.q0 ≈ 1.5 rtol = 1e-3 @test pe.params.qmax > 3.5 @test pe.params.qmax < 3.7 # Magnetic axis at R = R0, Z = 0 for the shifted-circle benchmark. - @test pe.ro ≈ 4.0 rtol = 1e-3 + @test pe.ro ≈ 4.0 rtol = 1e-3 @test abs(pe.zo) < 1e-8 end @@ -46,12 +46,12 @@ using GeneralizedPerturbedEquilibrium.Equilibrium: TJAnalyticConfig, Equilibrium # ε = 0.60 sits on the stable side of the ideal-external-kink pole at # ε ≈ 0.665 for this (qc, qa, pc, μ) combination. Pole-approach shape # (δW_t small, Δ' > 0 and growing) is the Option B success criterion. - tj = TJAnalyticConfig(lar_r0 = 1.0 / 0.60, lar_a = 1.0, - qc = 1.5, qa = 3.6, pc = 0.001, mu = 2.0, B0 = 12.0, - ma = 64, mtau = 64) - eq = EquilibriumConfig(eq_type = "tj_analytic_direct", - psilow = 0.01, psihigh = 0.995, - mpsi = 64, mtheta = 128, etol = 1e-7) + tj = TJAnalyticConfig(lar_r0=1.0 / 0.60, lar_a=1.0, + qc=1.5, qa=3.6, pc=0.001, mu=2.0, B0=12.0, + ma=64, mtau=64) + eq = EquilibriumConfig(eq_type="tj_analytic_direct", + psilow=0.01, psihigh=0.995, + mpsi=64, mtheta=128, etol=1e-7) pe = setup_equilibrium(eq, tj) @test pe.psio > 0 @@ -59,13 +59,13 @@ using GeneralizedPerturbedEquilibrium.Equilibrium: TJAnalyticConfig, Equilibrium # Direct-GS line integration at ε=0.60 gives qmax between 3.8 and 4.0. # If the εa³·L shape terms in f_R / f_Z regress, qmax jumps above 5. - @test pe.params.q0 ≈ 1.5 rtol = 1e-2 + @test pe.params.q0 ≈ 1.5 rtol = 1e-2 @test pe.params.qmax > 3.75 @test pe.params.qmax < 4.1 # Magnetic axis at R = R0. Shafranov shift of the O-point itself is # zero by construction (H₁(0) = 0). - @test pe.ro ≈ (1.0 / 0.60) rtol = 1e-3 + @test pe.ro ≈ (1.0 / 0.60) rtol = 1e-3 @test abs(pe.zo) < 1e-4 end @@ -73,18 +73,18 @@ using GeneralizedPerturbedEquilibrium.Equilibrium: TJAnalyticConfig, Equilibrium # At the magnetic axis ψ_in should equal psio (axis convention: ψ # positive at axis, zero at LCFS); sampling well outside the LCFS should # give a negative value (the vacuum branch of psi_rz). - tj = TJAnalyticConfig(lar_r0 = 1.0 / 0.25, lar_a = 1.0, - qc = 1.5, qa = 3.6, pc = 0.001, mu = 2.0, B0 = 12.0, - ma = 64, mtau = 64) - eq = EquilibriumConfig(eq_type = "tj_analytic_direct", - psilow = 0.01, psihigh = 0.995, - mpsi = 64, mtheta = 128, etol = 1e-7) + tj = TJAnalyticConfig(lar_r0=1.0 / 0.25, lar_a=1.0, + qc=1.5, qa=3.6, pc=0.001, mu=2.0, B0=12.0, + ma=64, mtau=64) + eq = EquilibriumConfig(eq_type="tj_analytic_direct", + psilow=0.01, psihigh=0.995, + mpsi=64, mtheta=128, etol=1e-7) inp = tj_analytic_run_direct(eq, tj) # ψ at the geometric axis matches psio (see DirectRunInput docstring for # the sign convention: psi_in is positive at axis, zero at LCFS). R0 = 1.0 / 0.25 - @test inp.psi_in((R0, 0.0)) ≈ inp.psio rtol = 1e-3 + @test inp.psi_in((R0, 0.0)) ≈ inp.psio rtol = 1e-3 # Well outside the LCFS → negative ψ_in (vacuum branch of the grid). R_out = R0 + 1.05 # plasma LCFS is at R ≈ R0 + 0.94 From 46c648dba59e537d0c9e2d4280e5cbc7c09cfa8b Mon Sep 17 00:00:00 2001 From: ebursch <76970916+ebursch@users.noreply.github.com> Date: Mon, 17 Aug 2026 11:54:48 -0400 Subject: [PATCH 4/9] WIP - Bcrit runs through, need to add true Q0, P, etc. and validate --- .../DIIID-like_SLAYER_example/slayer_ex.ipynb | 60 ++++++++++++++++++- .../CriticalResonantField/bcrit_dev.ipynb | 37 ++++++++++-- .../CriticalResonantField/bcrit_dev_ggj.ipynb | 43 ++++++++++++- src/Tearing/Runner/Runner.jl | 2 +- src/Tearing/Runner/run_slayer.jl | 14 +++-- 5 files changed, 145 insertions(+), 11 deletions(-) diff --git a/examples/DIIID-like_SLAYER_example/slayer_ex.ipynb b/examples/DIIID-like_SLAYER_example/slayer_ex.ipynb index 0fb8f9079..72901743a 100644 --- a/examples/DIIID-like_SLAYER_example/slayer_ex.ipynb +++ b/examples/DIIID-like_SLAYER_example/slayer_ex.ipynb @@ -30,7 +30,8 @@ "source": [ "using GeneralizedPerturbedEquilibrium\n", "using Plots\n", - "using GeneralizedPerturbedEquilibrium: Analysis" + "using GeneralizedPerturbedEquilibrium: Analysis\n", + "using Printf" ] }, { @@ -49,6 +50,63 @@ "id": "4", "metadata": {}, "outputs": [], + "source": [ + "using HDF5\n", + "\n", + "h5open(h5path, \"r\") do file\n", + " println(\"Top-level keys:\")\n", + " println(collect(keys(file)))\n", + "\n", + " if haskey(file, \"Tearing\")\n", + " println(\"\\nKeys in Tearing:\")\n", + " println(collect(keys(file[\"Tearing\"])))\n", + "\n", + " if haskey(file[\"Tearing\"], \"CriticalResonantField\")\n", + " println(\"\\nKeys in Tearing/CriticalResonantField:\")\n", + " println(collect(keys(file[\"Tearing\"][\"CriticalResonantField\"])))\n", + " end\n", + " else\n", + " println(\"No Tearing group found.\")\n", + " end\n", + "end" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5", + "metadata": {}, + "outputs": [], + "source": [ + "# Print the contents of the Tearing/CriticalResonantField group\n", + "h5open(h5path, \"r\") do file\n", + " if haskey(file, \"Tearing\") && haskey(file[\"Tearing\"], \"CriticalResonantField\")\n", + " println(\"\\nContents of Tearing/CriticalResonantField:\")\n", + " # Iterate over the keys in the Tearing/CriticalResonantField group and print their names and types\n", + " for key in keys(file[\"Tearing\"][\"CriticalResonantField\"])\n", + " dataset = file[\"Tearing\"][\"CriticalResonantField\"][key]\n", + " println(\"Key: $key, Type: $(typeof(dataset))\")\n", + " # print data \n", + " if isa(dataset, HDF5.Dataset)\n", + " data = read(dataset)\n", + " println(\"Data: $data\")\n", + " end\n", + " end\n", + " else\n", + " println(\"No Tearing/CriticalResonantField group found.\")\n", + " end\n", + " # Print bcrit data as .2e (in one line)\n", + " println(\"\\nBcrit data: $(join([@sprintf(\"%.2e\", x) for x in read(file[\"Tearing\"][\"CriticalResonantField\"][\"br_crit\"])], \" \"))\")\n", + "end\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6", + "metadata": {}, + "outputs": [], "source": [ "p_eq = Analysis.Equilibrium.plot_equilibrium_summary(h5path)\n", "p_ffs = Analysis.ForceFreeStates.plot_ffs_summary(h5path)\n", diff --git a/src/Tearing/CriticalResonantField/bcrit_dev.ipynb b/src/Tearing/CriticalResonantField/bcrit_dev.ipynb index 4af00e1f0..9269f6ab4 100644 --- a/src/Tearing/CriticalResonantField/bcrit_dev.ipynb +++ b/src/Tearing/CriticalResonantField/bcrit_dev.ipynb @@ -177,6 +177,35 @@ "id": "5", "metadata": {}, "outputs": [], + "source": [ + "jxbs = [-imag(1.0 / (d + 1e-2)) for d in Δs]\n", + "\n", + "p1 = plot(Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", + "plot!(p1, Qs, imag.(Δs), label=\"Im(Δ)\", lw=2)\n", + "xlabel!(p1, \"Q\")\n", + "ylabel!(p1, \"Δ\")\n", + "title!(p1, \"Inner-layer Δ(Q)\")\n", + "\n", + "p2 = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", + "xlabel!(p2, \"Q\")\n", + "ylabel!(p2, \"jxb\")\n", + "title!(p2, \"jxb(Q) = -Im[1/(Δ + δ_n_p)]\")\n", + "\n", + "p3 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2)\n", + "plot!(p3, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", + "xlabel!(p3, \"Q\")\n", + "ylabel!(p3, \"balance\")\n", + "title!(p3, \"2P(Q0-Q)/jxb\")\n", + "\n", + "plot(p1, p2, p3, layout=(3,1), size=(800, 1000))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6", + "metadata": {}, + "outputs": [], "source": [ "Qpk = Qs_positive[argmax(bal_positive)]\n", "j = findfirst(isequal(Qpk), Qs)\n", @@ -196,7 +225,7 @@ { "cell_type": "code", "execution_count": null, - "id": "6", + "id": "7", "metadata": {}, "outputs": [], "source": [ @@ -239,7 +268,7 @@ { "cell_type": "code", "execution_count": null, - "id": "7", + "id": "8", "metadata": {}, "outputs": [], "source": [ @@ -352,7 +381,7 @@ { "cell_type": "code", "execution_count": null, - "id": "8", + "id": "9", "metadata": {}, "outputs": [], "source": [] @@ -360,7 +389,7 @@ { "cell_type": "code", "execution_count": null, - "id": "9", + "id": "10", "metadata": {}, "outputs": [], "source": [] diff --git a/src/Tearing/CriticalResonantField/bcrit_dev_ggj.ipynb b/src/Tearing/CriticalResonantField/bcrit_dev_ggj.ipynb index a4d02d76f..ca4f3df48 100644 --- a/src/Tearing/CriticalResonantField/bcrit_dev_ggj.ipynb +++ b/src/Tearing/CriticalResonantField/bcrit_dev_ggj.ipynb @@ -106,7 +106,7 @@ "sval_ggj = 0.5\n", "\n", "tb = TorqueBalance(\n", - " GeneralizedPerturbedEquilibrium.InnerLayer.GGJModel(; solver=:ray),\n", + " GeneralizedPerturbedEquilibrium.InnerLayer.GGJModel(; solver=:galerkin),\n", " p_ggj,\n", " 0.5,\n", " 1.0,\n", @@ -204,6 +204,47 @@ "id": "10", "metadata": {}, "outputs": [], + "source": [ + "println(p.lu^(1/3))\n", + "println(p.tauk)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11", + "metadata": {}, + "outputs": [], + "source": [ + "Δs = [solve_inner(tb.model, tb.params, ComplexF64(q)).tearing/p.lu^(1 / 3) for q in Qs]\n", + "jxbs = [-imag(1.0 / (d + tb.delta_n_p)) for d in Δs]\n", + "\n", + "p1 = plot(Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", + "plot!(p1, Qs, imag.(Δs), label=\"Im(Δ)\", lw=2)\n", + "xlabel!(p1, \"Q\")\n", + "ylabel!(p1, \"Δ\")\n", + "title!(p1, \"Inner-layer Δ(Q)\")\n", + "\n", + "p2 = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", + "xlabel!(p2, \"Q\")\n", + "ylabel!(p2, \"jxb\")\n", + "title!(p2, \"jxb(Q) = -Im[1/(Δ + δ_n_p)]\")\n", + "\n", + "p3 = plot(Qs, real.(vals), label=\"Re(balance)\", lw=2)\n", + "plot!(p3, Qs, imag.(vals), label=\"Im(balance)\", lw=2)\n", + "xlabel!(p3, \"Q\")\n", + "ylabel!(p3, \"balance\")\n", + "title!(p3, \"2P(Q0-Q)/jxb\")\n", + "\n", + "plot(p1, p2, p3, layout=(3,1), size=(800, 1000))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "12", + "metadata": {}, + "outputs": [], "source": [ "p1 = plot(Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", "plot!(p1, Qs, imag.(Δs), label=\"Im(Δ)\", lw=2)\n", diff --git a/src/Tearing/Runner/Runner.jl b/src/Tearing/Runner/Runner.jl index df3293b2f..6f11208a7 100644 --- a/src/Tearing/Runner/Runner.jl +++ b/src/Tearing/Runner/Runner.jl @@ -30,7 +30,6 @@ using HDF5 using FastInterpolations: cubic_interp using ..Utilities using ..Utilities: KineticProfiles -using ...Equilibrium: read_kinetic_file, KineticProfileData using ..InnerLayer using ..InnerLayer: InnerLayerParameters, InnerLayerResponse, solve_inner, @@ -47,6 +46,7 @@ using ..Dispersion: SurfaceCoupling, surface_coupling, AMRResult, amr_scan, MultiBoxAMRResult, multi_box_amr_scan, as_amr_result, GrowthRateResult, find_growth_rates +using ..CriticalResonantField: TorqueBalance, torque_balance_scan include("Control.jl") include("Result.jl") diff --git a/src/Tearing/Runner/run_slayer.jl b/src/Tearing/Runner/run_slayer.jl index 3dca41bbc..5c92691f5 100644 --- a/src/Tearing/Runner/run_slayer.jl +++ b/src/Tearing/Runner/run_slayer.jl @@ -469,12 +469,18 @@ end and the corresponding critical resoannt field values for each rational surface. """ -function run_critical_resonant_field(equil, intr, ctrl; dir_path="./") +function run_critical_resonant_field(equil, intr, ctrl; dir_path="./", slayer_result=nothing) ctrl.enabled || return empty_critical_resonant_field_result() - # Use the same per-surface params already built for SLAYER - profiles = Equilibrium.load_kinetic_profiles(joinpath(dir_path, ctrl.profile_file)) - params = build_slayer_inputs(equil, intr.sing, profiles) + params = if slayer_result !== nothing && slayer_result.enabled && !isempty(slayer_result.params) + slayer_result.params + else + profiles = load_kinetic_profiles(joinpath(dir_path, ctrl.profile_file)) + build_slayer_inputs(equil, intr.sing, profiles) + end + + all(p -> p isa SLAYERParameters, params) || + throw(ArgumentError("CriticalResonantField requires SLAYERParameters; run SLAYER first or provide compatible params.")) surface_index = Int[] Qpeak_vec = Float64[] From 522312261253a0a8d0c81ca6d8e80938cb64bb49 Mon Sep 17 00:00:00 2001 From: ebursch <76970916+ebursch@users.noreply.github.com> Date: Tue, 18 Aug 2026 16:07:46 -0400 Subject: [PATCH 5/9] WIP - Rebasing with develop --- .../DIIID-like_SLAYER_example/slayer_ex.ipynb | 102 ++- .../CriticalResonantField/CRF Dev/b_crit.jls | Bin 0 -> 74 bytes .../CRF Dev/bcrit_dev.ipynb | 724 ++++++++++++++++++ .../{ => CRF Dev}/bcrit_dev_ggj.ipynb | 23 +- .../CRF Dev/bcrit_numerics.ipynb | 122 +++ .../{ => CRF Dev}/gslayer.txt | 0 .../CRF Dev/pole_testing.ipynb | 234 ++++++ .../CRF Dev/sample_number.jls | Bin 0 -> 68 bytes .../CriticalResonantField/TorqueBalance.jl | 4 +- .../CriticalResonantField/bcrit_dev.ipynb | 407 ---------- src/Tearing/Runner/HDF5Output.jl | 7 + src/Tearing/Runner/run_slayer.jl | 42 +- 12 files changed, 1211 insertions(+), 454 deletions(-) create mode 100644 src/Tearing/CriticalResonantField/CRF Dev/b_crit.jls create mode 100644 src/Tearing/CriticalResonantField/CRF Dev/bcrit_dev.ipynb rename src/Tearing/CriticalResonantField/{ => CRF Dev}/bcrit_dev_ggj.ipynb (91%) create mode 100644 src/Tearing/CriticalResonantField/CRF Dev/bcrit_numerics.ipynb rename src/Tearing/CriticalResonantField/{ => CRF Dev}/gslayer.txt (100%) create mode 100644 src/Tearing/CriticalResonantField/CRF Dev/pole_testing.ipynb create mode 100644 src/Tearing/CriticalResonantField/CRF Dev/sample_number.jls delete mode 100644 src/Tearing/CriticalResonantField/bcrit_dev.ipynb diff --git a/examples/DIIID-like_SLAYER_example/slayer_ex.ipynb b/examples/DIIID-like_SLAYER_example/slayer_ex.ipynb index 72901743a..709891273 100644 --- a/examples/DIIID-like_SLAYER_example/slayer_ex.ipynb +++ b/examples/DIIID-like_SLAYER_example/slayer_ex.ipynb @@ -8,36 +8,26 @@ "outputs": [], "source": [ "using Pkg\n", - "Pkg.activate(\"/Users/bursche/Documents/GitHub/JPEC_BCRIT\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1", - "metadata": {}, - "outputs": [], - "source": [ - "Base.active_project()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2", - "metadata": {}, - "outputs": [], - "source": [ + "Pkg.activate(\"/Users/bursche/Documents/GitHub/JPEC_BCRIT\")\n", + "Base.active_project()\n", + "\n", "using GeneralizedPerturbedEquilibrium\n", - "using Plots\n", "using GeneralizedPerturbedEquilibrium: Analysis\n", - "using Printf" + "using Printf\n", + "\n", + "using Plots\n", + "default(\n", + " fontfamily=\"Georgia\",\n", + " margin=12Plots.mm,\n", + " size=(800, 500),\n", + " dpi=150\n", + ")" ] }, { "cell_type": "code", "execution_count": null, - "id": "3", + "id": "1", "metadata": {}, "outputs": [], "source": [ @@ -47,7 +37,7 @@ { "cell_type": "code", "execution_count": null, - "id": "4", + "id": "2", "metadata": {}, "outputs": [], "source": [ @@ -74,7 +64,7 @@ { "cell_type": "code", "execution_count": null, - "id": "5", + "id": "3", "metadata": {}, "outputs": [], "source": [ @@ -101,12 +91,74 @@ "\n" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "4", + "metadata": {}, + "outputs": [], + "source": [ + "println(keys(h5open(h5path, \"r\")[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_1\"]))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5", + "metadata": {}, + "outputs": [], + "source": [ + "function bcrit_diag_plots(Δs, Qs, bal,name)\n", + "\n", + " p1 = plot(Qs, imag.(Δs), label=\"Im(Δ)\", lw=2)\n", + " #plot!(p1, Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", + " xlabel!(p1, \"Q\")\n", + " ylabel!(p1, \"Δ\")\n", + " title!(p1, \"Inner-layer Δ(Q) - $name\")\n", + "\n", + " p2 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2)\n", + " plot!(p2, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", + " xlabel!(p2, \"Q\")\n", + " ylabel!(p2, \"balance\")\n", + " title!(p2, \"2P(Q0-Q)/jxb - $name\")\n", + "\n", + " plot(p1, p2, layout=(2,1), size=(800, 1000))\n", + "\n", + "\n", + "end" + ] + }, { "cell_type": "code", "execution_count": null, "id": "6", "metadata": {}, "outputs": [], + "source": [ + "# Plot bcrit vs q surface\n", + "\n", + "# print all contents of bcrit /scan /surface 1/\n", + "h5open(h5path, \"r\") do file\n", + " bcrit = file[\"Tearing\"][\"CriticalResonantField\"]\n", + "\n", + " for i in 1:6\n", + " ss = \"surface_$i\"\n", + "\n", + " delta = read(bcrit[\"Scan\"][ss][\"delta\"])\n", + " Q = read(bcrit[\"Scan\"][ss][\"Q\"])\n", + " balance = read(bcrit[\"Scan\"][ss][\"balance\"])\n", + "\n", + " display(bcrit_diag_plots(delta, Q, balance, \"surface_$i\"))\n", + " end\n", + "end" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7", + "metadata": {}, + "outputs": [], "source": [ "p_eq = Analysis.Equilibrium.plot_equilibrium_summary(h5path)\n", "p_ffs = Analysis.ForceFreeStates.plot_ffs_summary(h5path)\n", diff --git a/src/Tearing/CriticalResonantField/CRF Dev/b_crit.jls b/src/Tearing/CriticalResonantField/CRF Dev/b_crit.jls new file mode 100644 index 0000000000000000000000000000000000000000..dcd8e2611787cf2ae06b76a1ee64426e4009ac8a GIT binary patch literal 74 zcmXr_@{waLoNTscITzal0AxrQ1ONa4 literal 0 HcmV?d00001 diff --git a/src/Tearing/CriticalResonantField/CRF Dev/bcrit_dev.ipynb b/src/Tearing/CriticalResonantField/CRF Dev/bcrit_dev.ipynb new file mode 100644 index 000000000..528ca4934 --- /dev/null +++ b/src/Tearing/CriticalResonantField/CRF Dev/bcrit_dev.ipynb @@ -0,0 +1,724 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "0", + "metadata": {}, + "outputs": [], + "source": [ + "using Pkg\n", + "Pkg.activate(\"/Users/bursche/Documents/GitHub/JPEC_BCRIT\")\n", + "Base.active_project()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1", + "metadata": {}, + "outputs": [], + "source": [ + "using GeneralizedPerturbedEquilibrium\n", + "using GeneralizedPerturbedEquilibrium: Analysis\n", + "using GeneralizedPerturbedEquilibrium: InnerLayer\n", + "using GeneralizedPerturbedEquilibrium.InnerLayer: solve_inner\n", + "using GeneralizedPerturbedEquilibrium: Tearing\n", + "using ..InnerLayer\n", + "using ..InnerLayer: InnerLayerModel, solve_inner, GGJModel, GGJParameters,\n", + " SLAYERModel, SLAYERParameters\n", + "\n", + "using Plots\n", + "using Printf\n", + "default(\n", + " fontfamily=\"Georgia\",\n", + " margin=12Plots.mm,\n", + " size=(800, 500),\n", + " dpi=150\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2", + "metadata": {}, + "outputs": [], + "source": [ + "struct TorqueBalance{M<:InnerLayerModel,P}\n", + " model::M\n", + " params::P\n", + " Q0::Float64\n", + " P::Float64\n", + " lu::Float64\n", + " sval::Float64\n", + "end\n", + "\n", + "function torque_balance_value(tb::TorqueBalance, Q::Number)\n", + " Δ = solve_inner(tb.model, tb.params, ComplexF64(Q)).tearing\n", + " alpha = 1e-2\n", + " jxb = -imag(1.0 / (Δ+ alpha))\n", + " return 2.0 * tb.P * (tb.Q0 - Q) / jxb, Δ\n", + "end\n", + "\n", + "function torque_balance_scan(tb; Qmin=-10.0, Qmax=10.0, n=200)\n", + " Qs = range(Qmin, Qmax; length=n)\n", + " torque_out = [torque_balance_value(tb, q) for q in Qs]\n", + " bal = [x[1] for x in torque_out]\n", + " Δs = [x[2] for x in torque_out]\n", + " #bal = [torque_balance_value(tb, q) for q in Qs]\n", + " positive = isfinite.(bal) .& (bal .> 0.0)\n", + "\n", + " if !any(positive)\n", + " return Qs, bal, NaN, NaN, 0.0, NaN, NaN, Δs\n", + " end\n", + " i = argmax(bal)\n", + " Qpeak_ind = i\n", + " Qs_positive = Qs[positive]\n", + " bal_positive = bal[positive]\n", + "\n", + " i = argmax(bal_positive)\n", + " Qpeak = Qs_positive[i]\n", + " \n", + " maxbal = bal_positive[i]\n", + "\n", + " br_crit = sqrt(maxbal / tb.lu * (tb.sval^2 / 2.0))\n", + " return Qs, bal, Qs_positive, bal_positive, Qpeak, br_crit, Qpeak_ind, Δs\n", + "end" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3", + "metadata": {}, + "outputs": [], + "source": [ + "p = GeneralizedPerturbedEquilibrium.InnerLayer.slayer_parameters(\n", + " n_e=1e19, t_e=1e3, t_i=1e3,\n", + " omega=0.0, omega_e=4, omega_i=-2,\n", + " qval=2.0, sval_r=0.5, bt=2.0, rs=1.0, R0=3.0, mu_i=2.0, zeff=1.0,\n", + " chi_perp=1.0, chi_tor=1.0, m=2, n=1\n", + ")\n", + "p2 = GeneralizedPerturbedEquilibrium.InnerLayer.SLAYERParameters(\n", + " ising=p.ising,\n", + " m=p.m, n=p.n,\n", + " tau=p.tau, lu=p.lu, c_beta=p.c_beta, D_norm=p.D_norm,\n", + " P_perp=p.P_perp, P_tor=p.P_tor,\n", + " Q_e=0.818, Q_i=-0.543, iota_e=p.iota_e,\n", + " tauk=p.tauk, tau_r=p.tau_r, delta_n=p.delta_n,\n", + " rs=p.rs, R0=p.R0, bt=p.bt, sval_r=p.sval_r,\n", + " dr_val=p.dr_val, dgeo_val=p.dgeo_val,\n", + " eta=p.eta, d_beta=p.d_beta,\n", + " dc_tmp=p.dc_tmp, dc_type=p.dc_type\n", + ")\n", + "\n", + "p2 = GeneralizedPerturbedEquilibrium.InnerLayer.SLAYERParameters(\n", + " ising=p.ising,\n", + " m=p.m, n=p.n,\n", + " tau=p.tau, lu=p.lu, c_beta=p.c_beta, D_norm=p.D_norm,\n", + " P_perp=p.P_perp, P_tor=p.P_tor,\n", + " Q_e=2, Q_i=3, iota_e=p.iota_e,\n", + " tauk=p.tauk, tau_r=p.tau_r, delta_n=p.delta_n,\n", + " rs=p.rs, R0=p.R0, bt=p.bt, sval_r=p.sval_r,\n", + " dr_val=p.dr_val, dgeo_val=p.dgeo_val,\n", + " eta=p.eta, d_beta=p.d_beta,\n", + " dc_tmp=p.dc_tmp, dc_type=p.dc_type\n", + ")\n", + "\n", + "p = p2\n", + "\n", + "tb = TorqueBalance(\n", + " GeneralizedPerturbedEquilibrium.InnerLayer.SLAYERModel(;),\n", + " p,\n", + " 0.5,\n", + " 61.0, #1.0\n", + " p.lu,\n", + " p.sval_r\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4", + "metadata": {}, + "outputs": [], + "source": [ + "#Qs = range(-5.0, 5.0, length=200)\n", + "\n", + "#vals = [torque_balance_value(tb, q) for q in Qs]\n", + "\"\"\"\n", + "n=2000:\n", + "Qpeak = 0.24512256128064033\n", + "maxbal = 0.35873684252530247\n", + "br_crit = 4.668551985584323e-5\n", + "\n", + "n=200 (def):\n", + "Qpeak = 0.25125628140703515\n", + "maxbal = 0.3585219071071706\n", + "br_crit = 4.667153206033017e-5\n", + "\"\"\"\n", + "Qmi = -10\n", + "Qma = 10\n", + "\n", + "Qs, bal, Qs_positive, bal_positive, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb,Qmin=Qmi, Qmax=Qma, n=10000)\n", + "\n", + "println(\"Qpeak = \", Qpeak)\n", + "println(\"maxbal = \", maximum(bal_positive))\n", + "println(\"maxbal = \", maximum(bal))\n", + "println(\"br_crit = \", brcrit)\n", + "\n", + "p1 = plot(Qs, bal, lw=2, label=\"balance\")#,ylim=(-40, 40))\n", + "z_inds = findall(i -> bal[i]*bal[i+1] < 0, 1:length(bal)-1)\n", + "println(\"zero crossings at Q = \", Qs[z_inds])\n", + "for i in z_inds\n", + " vline!([Qs[i]], label=\"0\", linestyle=:dot, color=:gray)\n", + "end\n", + "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", + "xlabel!(\"Q\")\n", + "ylabel!(\"balance\")\n", + "title!(\"Torque-balance scan\")\n", + "\n", + "\n", + "\n", + "p5 = plot(Qs, bal, lw=2, label=\"balance\",xlim=(Qs[z_inds[1]],Qs[z_inds[2]]))#,ylim=(-40, 40))#, xlim = (-.11,-.09))\n", + "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", + "xlabel!(\"Q\")\n", + "ylabel!(\"balance\")\n", + "title!(\"Torque-balance scan\")\n", + "\n", + "p2 = plot(Qs, -imag(Δs), lw=2, label=\"Im(Δ)\",ylim=(-5,2))#,xlim=(-.11,-.09))\n", + "plot!(p2, Qs, real(Δs), lw=2, label=\"Re(Δ)\")\n", + "#vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + "#hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", + "vline!([-3], linestyle=:dashdot)\n", + "vline!([-2], linestyle=:dashdot)\n", + "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + "vline!([0.499], linestyle=:dashdot)\n", + "xlabel!(\"Q\")\n", + "ylabel!(\"Δ\")\n", + "title!(\"Torque-balance scan\")\n", + "\n", + "jxb = -imag(1.0 ./ (Δs .+ 1e-2))\n", + "jxb0 = -imag(1.0 ./ (Δs))\n", + "p3 = plot(Qs, jxb, lw=2, label=\"-Im(1 / (Δs + 1e-2))\",color=:blue)#, xlim = (-.11,-.09),ylim=(-500,500))\n", + "plot!(p3, Qs, jxb0, lw=2, label=\"-Im(1 / Δs)\",color=:red,linestyle=:dash)\n", + "xlabel!(\"Q\")\n", + "ylabel!(\"~ jxb\")\n", + "\n", + "p4 = plot(Qs, jxb, lw=2, label=\"-Im(1 / Δs)\",color=:blue)#, xlim = (-.11,-.09))\n", + "xlabel!(\"Q\")\n", + "ylabel!(\"~ jxb\")\n", + "\"\"\"\n", + "#remake plot 1 but of derivative of balance with respect to Q\n", + "dQ = Qs[2] - Qs[1]\n", + "dbal_dQ = diff(bal) ./ dQ\n", + "p3 = plot(Qs[1:end-1], dbal_dQ, lw=2, label=\"d(balance)/dQ\",ylim=(-1000, 1000))\n", + "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", + "xlabel!(\"Q\")\n", + "ylabel!(\"d(balance)/dQ\")\n", + "\"\"\"\n", + "\n", + "Qs, bal, Qs_positive, bal_positive, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb,Qmin=Qs[], Qmax=Qs[zin], n=10000)\n", + "\n", + "\n", + "plo = plot(p1, p2,p3,p4,p5, p6, layout=(6,1), size=(1000, 2000))\n", + "display(plo)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5", + "metadata": {}, + "outputs": [], + "source": [ + "Qlow = -0.1005100510051005\n", + "Qhigh = 0.49954995499549953\n", + "\n", + "#Qs, bal, Qs_positive, bal_positive, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb,Qmin=Qlow, Qmax=Qhigh, n=10000)\n", + "\n", + "println(\"Qpeak = \", Qpeak)\n", + "println(\"maxbal = \", maximum(bal_positive))\n", + "println(\"maxbal = \", maximum(bal))\n", + "println(\"br_crit = \", brcrit)\n", + "\n", + "p1 = plot(Qs, bal, lw=2, label=\"balance\")#,ylim=(-40, 40))\n", + "z_inds = findall(i -> bal[i]*bal[i+1] < 0, 1:length(bal)-1)\n", + "println(\"zero crossings at Q = \", Qs[z_inds])\n", + "for i in z_inds\n", + " vline!([Qs[i]], label=\"0\", linestyle=:dot, color=:gray)\n", + "end\n", + "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", + "xlabel!(\"Q\")\n", + "ylabel!(\"balance\")\n", + "title!(\"Torque-balance scan\")\n", + "\n", + "\n", + "p5 = plot(Qs, bal, lw=2, label=\"balance\",ylim=(-40, 40), xlim = (-.11,-.09))\n", + "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", + "xlabel!(\"Q\")\n", + "ylabel!(\"balance\")\n", + "title!(\"Torque-balance scan\")\n", + "\n", + "p2 = plot(Qs, -imag(Δs), lw=2, label=\"Im(Δ)\",ylim=(-2,2))#,xlim=(-.11,-.09))\n", + "plot!(p2, Qs, real(Δs), lw=2, label=\"Re(Δ)\")\n", + "#vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + "#hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", + "xlabel!(\"Q\")\n", + "ylabel!(\"Δ\")\n", + "title!(\"Torque-balance scan\")\n", + "\n", + "jxb = -imag(1.0 ./ (Δs .+ 1e-2))\n", + "jxb0 = -imag(1.0 ./ (Δs))\n", + "p3 = plot(Qs, jxb, lw=2, label=\"-Im(1 / (Δs + 1e-2))\",color=:blue, xlim = (-.11,-.09),ylim=(-500,500))\n", + "plot!(p3, Qs, jxb0, lw=2, label=\"-Im(1 / Δs)\",color=:red,linestyle=:dash)\n", + "xlabel!(\"Q\")\n", + "ylabel!(\"~ jxb\")\n", + "\n", + "p4 = plot(Qs, jxb, lw=2, label=\"-Im(1 / Δs)\",color=:blue, xlim = (-.11,-.09))\n", + "xlabel!(\"Q\")\n", + "ylabel!(\"~ jxb\")\n", + "\"\"\"\n", + "#remake plot 1 but of derivative of balance with respect to Q\n", + "dQ = Qs[2] - Qs[1]\n", + "dbal_dQ = diff(bal) ./ dQ\n", + "p3 = plot(Qs[1:end-1], dbal_dQ, lw=2, label=\"d(balance)/dQ\",ylim=(-1000, 1000))\n", + "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", + "xlabel!(\"Q\")\n", + "ylabel!(\"d(balance)/dQ\")\n", + "\"\"\"\n", + "plo = plot(p1, p2,p3,p4,p5, layout=(5,1), size=(1000, 2000))\n", + "display(plo)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6", + "metadata": {}, + "outputs": [], + "source": [ + "#Qs = range(-5.0, 5.0, length=200)\n", + "\n", + "#vals = [torque_balance_value(tb, q) for q in Qs]\n", + "\"\"\"\n", + "n=2000:\n", + "Qpeak = 0.24512256128064033\n", + "maxbal = 0.35873684252530247\n", + "br_crit = 4.668551985584323e-5\n", + "\n", + "n=200 (def):\n", + "Qpeak = 0.25125628140703515\n", + "maxbal = 0.3585219071071706\n", + "br_crit = 4.667153206033017e-5\n", + "\"\"\"\n", + "\n", + "#Qs, bal, Qs_positive, bal_positive, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb,Qmin=-.2, Qmax=0.5, n=10000)\n", + "\n", + "println(\"Qpeak = \", Qpeak)\n", + "println(\"maxbal = \", maximum(bal_positive))\n", + "println(\"maxbal = \", maximum(bal))\n", + "println(\"br_crit = \", brcrit)\n", + "\n", + "p1 = plot(Qs, bal, lw=2, label=\"balance\")#,ylim=(-40, 40))\n", + "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", + "xlabel!(\"Q\")\n", + "ylabel!(\"balance\")\n", + "title!(\"Torque-balance scan\")\n", + "\n", + "p2 = plot(Qs, -imag(Δs), lw=2, label=\"Im(Δs)\")#,ylim=(-.2,.05))#,xlim=(-.11,-.09))\n", + "plot!(p2, Qs, real(Δs), lw=2, label=\"Re(Δs)\")\n", + "#vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + "#hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", + "xlabel!(\"Q\")\n", + "ylabel!(\"Δs\")\n", + "title!(\"Torque-balance scan\")\n", + "\n", + "\"\"\"\n", + "#remake plot 1 but of derivative of balance with respect to Q\n", + "dQ = Qs[2] - Qs[1]\n", + "dbal_dQ = diff(bal) ./ dQ\n", + "p3 = plot(Qs[1:end-1], dbal_dQ, lw=2, label=\"d(balance)/dQ\",ylim=(-1000, 1000))\n", + "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", + "xlabel!(\"Q\")\n", + "ylabel!(\"d(balance)/dQ\")\n", + "\"\"\"\n", + "plo = plot(p1, p2, layout=(2,1), size=(800, 1000))\n", + "display(plo)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7", + "metadata": {}, + "outputs": [], + "source": [ + "jxbs = [-imag(1.0 / (d + 1e-2)) for d in Δs]\n", + "\n", + "p1 = plot(Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", + "plot!(p1, Qs, imag.(Δs), label=\"Im(Δ)\", lw=2)\n", + "xlabel!(p1, \"Q\")\n", + "ylabel!(p1, \"Δ\")\n", + "title!(p1, \"Inner-layer Δ(Q)\")\n", + "\n", + "p2 = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", + "xlabel!(p2, \"Q\")\n", + "ylabel!(p2, \"jxb\")\n", + "title!(p2, \"jxb(Q) = -Im[1/(Δ + δ_n_p)]\")\n", + "\n", + "p3 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2)\n", + "plot!(p3, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", + "xlabel!(p3, \"Q\")\n", + "ylabel!(p3, \"balance\")\n", + "title!(p3, \"2P(Q0-Q)/jxb\")\n", + "\n", + "plot(p1, p2, p3, layout=(3,1), size=(800, 1000))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8", + "metadata": {}, + "outputs": [], + "source": [ + "# Check torque is balanced\n", + "\n", + "viscous_torque = 2*tb.P*(tb.Q0 - Qpeak)\n", + "electromagnetic_torque = -imag(1.0 / (Δs[Qpeak_ind] + 1e-2)) *brcrit^2*tb.lu/(tb.sval^2/2)\n", + "\n", + "# delta_n_p = 1e-2\n", + "# jxb = -imag(1.0 / (Δ + delta_n_p))\n", + "# bal = 2.0 * tb.P * (tb.Q0 - Q) / jxb\n", + "# br_crit = sqrt(maxbal / tb.lu * (tb.sval^2 / 2.0))\n", + "\n", + "@printf(\"br_crit = %.5e\\n\", brcrit)\n", + "@printf(\"viscous_torque = %.5e\\n\", viscous_torque)\n", + "@printf(\"electromagnetic_torque = %.5e\\n\", electromagnetic_torque)\n", + "@printf(\"ratio = %.10f\\n\", viscous_torque / electromagnetic_torque)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9", + "metadata": {}, + "outputs": [], + "source": [ + "Qs_n, bal_n, Qs_positive_n, bal_positive_n, Qpeak_n, brcrit_n, Qpeak_ind_n, Δs_n = torque_balance_scan(tb,Qmin=-3, Qmax=3, n=2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "10", + "metadata": {}, + "outputs": [], + "source": [ + "sample_number = [2, 3, 4, 5, 10,100,1000]#,10000,100000]#,1000000]\n", + "b_crit = []\n", + "# make dicts to store Qs_n and Δs_n arrays for each sample number\n", + "Qs_n_dict = Dict{Int, Vector{Float64}}()\n", + "bal_n_dict = Dict{Int, Vector{Float64}}()\n", + "for i in sample_number\n", + " Qs_n, bal_n, Qs_positive_n, bal_positive_n, Qpeak_n, brcrit_n, Qpeak_ind_n, Δs_n = torque_balance_scan(tb,Qmin=-3, Qmax=3, n=i)\n", + " push!(b_crit, brcrit_n)\n", + " push!(Qs_n_dict, i => Qs_n)\n", + " push!(bal_n_dict, i => bal_n)\n", + " println(bal_n)\n", + "end\n", + "\n", + "# add bcrit = 3.50601e-03 for n=100000 to b_crit\n", + "#push!(b_crit, 3.50601e-03)\n", + "\n", + "# make a plot of b_crit vs sample_number \n", + "p1 = plot(sample_number, b_crit,\n", + " lw=2,\n", + " label=\"b_crit\",\n", + " #xscale=:log10,\n", + " #yscale=:log10,\n", + " xlabel=\"Sample Number\",\n", + " ylabel=\"b_crit\")\n", + "\n", + "p2 = plot(\n", + " xlabel=\"Q\",\n", + " ylabel=\"balance\",\n", + " title=\"Torque balance vs Q\"\n", + ")\n", + "\n", + "for i in sample_number[1:end-1]\n", + " plot!(p2, Qs_n_dict[i], bal_n_dict[i],\n", + " lw=2,\n", + " label=\"n=$i\")\n", + "end\n", + "\n", + "p3 = plot(layout=(3, 2), size=(1000, 800))\n", + "\n", + "for (k, i) in enumerate(sample_number[1:end-1])\n", + " plot!(\n", + " p3[k],\n", + " Qs_n_dict[i],\n", + " bal_n_dict[i],\n", + " lw=2,\n", + " label=\"n=$i\",\n", + " xlabel=\"Q\",\n", + " ylabel=\"balance\",\n", + " title=\"n = $i\"\n", + " )\n", + "end\n", + "\n", + "display(p1)\n", + "display(p2)\n", + "display(p3)\n", + "\n", + "\n", + "println(\"b_crit = \", b_crit)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11", + "metadata": {}, + "outputs": [], + "source": [ + "println(b_crit)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "12", + "metadata": {}, + "outputs": [], + "source": [ + "bcrit = Any[0.0014075170156654356, 0.0015190532807794722, 0.0015297173529485084, 0.0015297510027746748, 0.0015297613496804952, 0.0015297692159317363, 0.004702965572292843]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13", + "metadata": {}, + "outputs": [], + "source": [ + "using Serialization\n", + "\n", + "# serialize(\"Qs_n_dict.jls\", Qs_n_dict)\n", + "# serialize(\"bal_n_dict.jls\", bal_n_dict)\n", + "# serialize(\"b_crit.jls\", b_crit)\n", + "# serialize(\"sample_number.jls\", sample_number)\n", + "#my_dict = deserialize(\"my_dict.jls\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "14", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "Qs, bal, Qs_positive, bal_positive, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb,Qmin=-2.5, Qmax=0, n=20000)\n", + "\n", + "jxbs = [-imag(1.0 / (d + 1e-2)) for d in Δs]\n", + "T_VISC = [2.0 * tb.P * (tb.Q0 - q) for q in Qs] #(q, jxb) in zip(Qs, jxbs)]\n", + "br_t = brcrit\n", + "println(tb.lu, \" \", tb.sval, \" \", br_t, \" \", p.bt, \" \", 1e-2)\n", + "@printf(\"br_crit = %.5e\\n\", brcrit)\n", + "#T_EM = tb.lu * tb.sval^2/2 * (brcrit)^2 * jxbs\n", + "T_EM = -imag(1.0 ./ (Δs .+ 1e-2)) *brcrit^2*tb.lu/(tb.sval^2/2)\n", + "i = Qpeak_ind\n", + "println(T_VISC[i]/(tb.lu * tb.sval^2/2 * (brcrit)^2 * jxbs[i]))\n", + "println(T_VISC[i] / (tb.lu * tb.sval^2/2 * (brcrit * p.bt)^2 * jxbs[i]))\n", + "println(T_VISC[i] / ( (brcrit / p.bt)^2 * jxbs[i]))\n", + "\n", + "#T_EM ∝ S ξ̂ (br/Bφ)² Im[-Δ̂(Q)⁻¹]\n", + "#T_visc ∝ 2 P (Q0 − Q)\n", + "\n", + "xmi = -2.5\n", + "xma = 0\n", + "\n", + "\"\"\"\n", + "p1 = plot(Qs, imag.(Δs), label=\"Im(Δ)\", lw=2, xlim=(xmi, xma))\n", + "#plot!(p1, Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", + "xlabel!(p1, \"Q\")\n", + "ylabel!(p1, \"Δ\")\n", + "#title!(p1, \"Inner-layer Δ(Q)\")\n", + "\"\"\"\n", + "\n", + "p1 = plot( Qs, T_VISC, label=\"T_V\", lw=2, xlim=(xmi, xma))#,ylim=(-1000,1000))\n", + "plot!(p1, Qs, T_EM, label=\"T_EM\", lw=2)\n", + "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + "xlabel!(p1, \"Q\")\n", + "ylabel!(p1, \"Torque\")\n", + "\n", + "#p2 = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", + "p2 = plot( Qs, T_VISC, label=\"T_V\", lw=2, xlim=(xmi, xma))#,ylim=(0,500))\n", + "plot!(p2, Qs, T_EM, label=\"T_EM\", lw=2)\n", + "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + "xlabel!(p2, \"Q\")\n", + "ylabel!(p2, \"Torque\")\n", + "#title!(p2, \"jxb(Q) = -Im[1/(Δ + δ_n_p)]\")\n", + "\n", + "p3 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2, xlim=(xmi, xma))\n", + "plot!(p3, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", + "ylabel!(p3, \"Torque Balance\")\n", + "#title!(p3, \"2P(Q0-Q)/jxb\")\n", + "xlabel!(p3, \"Q\")\n", + "vline!([Qpeak], label=\"Max Balance\", linestyle=:dash)\n", + "\n", + "plot(p1, p2, p3, layout=(3,1), size=(800, 1000))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "15", + "metadata": {}, + "outputs": [], + "source": [ + "# Recreate Cihan's plot:\n", + "\n", + "using Plots\n", + "using DataInterpolations\n", + "\n", + "default(\n", + " fontfamily=\"Georgia\",\n", + " grid=false,\n", + " linewidth=2,\n", + " guidefontsize=26,\n", + " tickfontsize=18,\n", + " titlefontsize=30,\n", + " legendfontsize=18,\n", + " size=(1200, 800),\n", + " dpi=150\n", + ")\n", + "\n", + "# Build the critical boundary bcrit(Q0)\n", + "Q0_scan = range(-1.0, 4.5; length=80)\n", + "bcrit_curve = Float64[]\n", + "\n", + "for Q0 in Q0_scan\n", + " tbQ = TorqueBalance(\n", + " tb.model,\n", + " tb.params,\n", + " Float64(Q0),\n", + " tb.P,\n", + " tb.delta_n_p,\n", + " tb.lu,\n", + " tb.sval\n", + " )\n", + "\n", + " Qs, bal, Qs_pos, bal_pos, Qpeak, brcrit, Qpeak_ind, Δs =\n", + " torque_balance_scan(tbQ; Qmin=-10.0, Qmax=10.0, n=250)\n", + "\n", + " if isempty(bal_pos) || !all(isfinite.(bal_pos)) || maximum(bal_pos) <= 0\n", + " push!(bcrit_curve, NaN)\n", + " else\n", + " push!(bcrit_curve, brcrit)\n", + " end\n", + "end\n", + "\n", + "ok = isfinite.(bcrit_curve)\n", + "Q0_plot = Q0_scan[ok]\n", + "bcrit_plot = bcrit_curve[ok]\n", + "\n", + "perm = sortperm(Q0_plot)\n", + "Q0_plot = Q0_plot[perm]\n", + "bcrit_plot = bcrit_plot[perm]\n", + "\n", + "# Interpolate the boundary: bcrit = f(Q0)\n", + "curve_itp = LinearInterpolation(bcrit_plot, Q0_plot)\n", + "\n", + "# Full phase-box bounds\n", + "x0 = minimum(bcrit_plot) * 0.8\n", + "x1 = maximum(bcrit_plot) * 1.2\n", + "y0 = minimum(Q0_plot)\n", + "y1 = maximum(Q0_plot)\n", + "\n", + "xvals = range(x0, x1; length=350)\n", + "yvals = range(y0, y1; length=350)\n", + "\n", + "locked_mask = zeros(Float64, length(yvals), length(xvals))\n", + "for iy in eachindex(yvals)\n", + " y = yvals[iy]\n", + " for ix in eachindex(xvals)\n", + " x = xvals[ix]\n", + " # locked when bcrit exceeds the boundary for that Q0\n", + " locked_mask[iy, ix] = x >= curve_itp(y) ? 1.0 : 0.0\n", + " end\n", + "end\n", + "\n", + "p = contourf(\n", + " xvals, yvals, locked_mask',\n", + " levels=[-0.5, 0.5, 1.5],\n", + " c=[:navy, :firebrick],\n", + " colorbar=false,\n", + " xlabel=\"b_crit\",\n", + " ylabel=\"Q_0\",\n", + " title=\"Locked / unlocked region\",\n", + " framestyle=:box,\n", + " xlims=(x0, x1),\n", + " ylims=(y0, y1),\n", + " legend=false\n", + ")\n", + "\n", + "# Critical boundary\n", + "plot!(p, bcrit_plot, Q0_plot; lw=3, color=:black, label=\"critical boundary\")\n", + "\n", + "# Critical point\n", + "cp_idx = argmax(bcrit_plot)\n", + "cp_x = bcrit_plot[cp_idx]\n", + "cp_y = Q0_plot[cp_idx]\n", + "scatter!(p, [cp_x], [cp_y]; color=:gold, marker=:star5, ms=12, label=\"critical point\")\n", + "\n", + "# Single legend block with one entry per category\n", + "plot!(p, [NaN], [NaN]; color=:firebrick, lw=4, label=\"locked\")\n", + "plot!(p, [NaN], [NaN]; color=:navy, lw=4, label=\"unlocked\")\n", + "plot!(p, [NaN], [NaN]; color=:black, lw=3, label=\"critical boundary\")\n", + "scatter!(p, [NaN], [NaN]; color=:gold, marker=:star5, ms=12, label=\"critical point\")\n", + "\n", + "plot!(p; legend=:topright)\n", + "\n", + "display(p)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "16", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "17", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/src/Tearing/CriticalResonantField/bcrit_dev_ggj.ipynb b/src/Tearing/CriticalResonantField/CRF Dev/bcrit_dev_ggj.ipynb similarity index 91% rename from src/Tearing/CriticalResonantField/bcrit_dev_ggj.ipynb rename to src/Tearing/CriticalResonantField/CRF Dev/bcrit_dev_ggj.ipynb index ca4f3df48..617d61585 100644 --- a/src/Tearing/CriticalResonantField/bcrit_dev_ggj.ipynb +++ b/src/Tearing/CriticalResonantField/CRF Dev/bcrit_dev_ggj.ipynb @@ -216,7 +216,26 @@ "metadata": {}, "outputs": [], "source": [ - "Δs = [solve_inner(tb.model, tb.params, ComplexF64(q)).tearing/p.lu^(1 / 3) for q in Qs]\n", + "plt.figure()\n", + "for i in OMFIT['GPEC']['OUTPUTS'].keys():\n", + " try:\n", + " print(OMFIT['GPEC']['OUTPUTS'][i]['DATA'][0]['gpec_slayer_torque_balance_m2_n1_out']['bal'].values)\n", + " plt.plot(OMFIT['GPEC']['OUTPUTS'][i]['DATA'][0]['gpec_slayer_torque_balance_m2_n1_out']['inQ'].values, OMFIT['GPEC']['OUTPUTS'][i]['DATA'][0]['gpec_slayer_torque_balance_m2_n1_out']['bal'].values,label=i)\n", + " except:\n", + " continue\n", + "plt.axhline(0)\n", + "plt.legend()\n", + " \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "12", + "metadata": {}, + "outputs": [], + "source": [ + "Δs = [solve_inner(tb.model, tb.params, ComplexF64(q)).tearing/p.lu^(1 / 3)/p.rs for q in Qs]\n", "jxbs = [-imag(1.0 / (d + tb.delta_n_p)) for d in Δs]\n", "\n", "p1 = plot(Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", @@ -242,7 +261,7 @@ { "cell_type": "code", "execution_count": null, - "id": "12", + "id": "13", "metadata": {}, "outputs": [], "source": [ diff --git a/src/Tearing/CriticalResonantField/CRF Dev/bcrit_numerics.ipynb b/src/Tearing/CriticalResonantField/CRF Dev/bcrit_numerics.ipynb new file mode 100644 index 000000000..71ed79d9e --- /dev/null +++ b/src/Tearing/CriticalResonantField/CRF Dev/bcrit_numerics.ipynb @@ -0,0 +1,122 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "0", + "metadata": {}, + "outputs": [], + "source": [ + "using Pkg\n", + "Pkg.activate(\"/Users/bursche/Documents/GitHub/JPEC_BCRIT\")\n", + "Base.active_project()\n", + "using GeneralizedPerturbedEquilibrium\n", + "using GeneralizedPerturbedEquilibrium: Analysis\n", + "using GeneralizedPerturbedEquilibrium: InnerLayer\n", + "using GeneralizedPerturbedEquilibrium.InnerLayer: solve_inner\n", + "using GeneralizedPerturbedEquilibrium: Tearing\n", + "using ..InnerLayer\n", + "using ..InnerLayer: InnerLayerModel, solve_inner, GGJModel, GGJParameters,\n", + " SLAYERModel, SLAYERParameters\n", + "using Serialization\n", + "using Plots\n", + "using Printf\n", + "default(\n", + " fontfamily=\"Georgia\",\n", + " margin=12Plots.mm,\n", + " size=(800, 500),\n", + " dpi=150\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1", + "metadata": {}, + "outputs": [], + "source": [ + "bal_n_dict = deserialize(\"bal_n_dict.jls\")\n", + "Qs_n_dict = deserialize(\"Qs_n_dict.jls\")\n", + "sample_number = deserialize(\"sample_number.jls\")\n", + "bcrit = deserialize(\"b_crit.jls\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2", + "metadata": {}, + "outputs": [], + "source": [ + "# make a plot of b_crit vs sample_number \n", + "p1 = plot(\n", + " sample_number,\n", + " b_crit,\n", + " lw=2,\n", + " marker=:circle,\n", + " label=\"b_crit\",\n", + " xscale=:log10,\n", + " #yscale=:log10,\n", + " xlabel=\"Sample Number\",\n", + " ylabel=\"b_crit\"\n", + ")\n", + "\n", + "xticks!(p1,\n", + " [5, 10, 100, 1000, 10000, 100000, 1000000],\n", + " [\"5\", \"10\", \"100\", \"1k\", \"10k\", \"100k\", \"1M\"]\n", + ")\n", + "\n", + "p2 = plot(\n", + " xlabel=\"Q\",\n", + " ylabel=\"balance\",\n", + " title=\"Torque balance vs Q\"\n", + ")\n", + "\n", + "for i in sample_number\n", + " plot!(p2, Qs_n_dict[i], bal_n_dict[i],\n", + " lw=2,\n", + " label=\"n=$i\")\n", + "end\n", + "\n", + "p3 = plot(layout=(4, 2), size=(1000, 800))\n", + "\n", + "for (k, i) in enumerate(sample_number)\n", + " plot!(\n", + " p3[k],\n", + " Qs_n_dict[i],\n", + " bal_n_dict[i],\n", + " lw=2,\n", + " label=\"n=$i\",\n", + " xlabel=\"Q\",\n", + " ylabel=\"balance\",\n", + " title=\"n = $i\"\n", + " )\n", + "end\n", + "\n", + "display(p1)\n", + "display(p2)\n", + "display(p3)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3", + "metadata": {}, + "outputs": [], + "source": [ + "println(\"bcrit = $bcrit\")" + ] + } + ], + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/src/Tearing/CriticalResonantField/gslayer.txt b/src/Tearing/CriticalResonantField/CRF Dev/gslayer.txt similarity index 100% rename from src/Tearing/CriticalResonantField/gslayer.txt rename to src/Tearing/CriticalResonantField/CRF Dev/gslayer.txt diff --git a/src/Tearing/CriticalResonantField/CRF Dev/pole_testing.ipynb b/src/Tearing/CriticalResonantField/CRF Dev/pole_testing.ipynb new file mode 100644 index 000000000..329e9dd53 --- /dev/null +++ b/src/Tearing/CriticalResonantField/CRF Dev/pole_testing.ipynb @@ -0,0 +1,234 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "0", + "metadata": {}, + "outputs": [], + "source": [ + "using Pkg\n", + "Pkg.activate(\"/Users/bursche/Documents/GitHub/JPEC_BCRIT\")\n", + "Base.active_project()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1", + "metadata": {}, + "outputs": [], + "source": [ + "using GeneralizedPerturbedEquilibrium\n", + "using GeneralizedPerturbedEquilibrium: Analysis\n", + "using GeneralizedPerturbedEquilibrium: InnerLayer\n", + "using GeneralizedPerturbedEquilibrium.InnerLayer: solve_inner\n", + "using GeneralizedPerturbedEquilibrium: Tearing\n", + "using ..InnerLayer\n", + "using ..InnerLayer: InnerLayerModel, solve_inner, GGJModel, GGJParameters,\n", + " SLAYERModel, SLAYERParameters\n", + "\n", + "using Plots\n", + "using Printf\n", + "default(\n", + " fontfamily=\"Georgia\",\n", + " margin=12Plots.mm,\n", + " size=(800, 500),\n", + " dpi=150\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2", + "metadata": {}, + "outputs": [], + "source": [ + "struct TorqueBalance{M<:InnerLayerModel,P}\n", + " model::M\n", + " params::P\n", + " Q0::Float64\n", + " P::Float64\n", + " lu::Float64\n", + " sval::Float64\n", + "end\n", + "\n", + "function torque_balance_value(tb::TorqueBalance, Q::Number)\n", + " Δ = solve_inner(tb.model, tb.params, ComplexF64(Q)).tearing\n", + " alpha = 1e-2\n", + " jxb = -imag(1.0 / (Δ + alpha))\n", + " return 2.0 * tb.P * (tb.Q0 - Q) / jxb, Δ\n", + "end\n", + "\n", + "function torque_balance_scan(tb; Qmin=-10.0, Qmax=10.0, n=200)\n", + " Qs = range(Qmin, Qmax; length=n)\n", + " torque_out = [torque_balance_value(tb, q) for q in Qs]\n", + " bal = [x[1] for x in torque_out]\n", + " Δs = [x[2] for x in torque_out]\n", + " #bal = [torque_balance_value(tb, q) for q in Qs]\n", + " positive = isfinite.(bal) .& (bal .> 0.0)\n", + "\n", + " if !any(positive)\n", + " return Qs, bal, NaN, NaN, 0.0, NaN, NaN, Δs\n", + " end\n", + "\n", + " i = argmax(bal)\n", + " Qpeak_ind = i\n", + " Qs_positive = Qs[positive]\n", + " bal_positive = bal[positive]\n", + "\n", + "\n", + " \n", + " Qpeak = Qs_positive[i]\n", + " maxbal = bal_positive[i]\n", + "\n", + " br_crit = sqrt(maxbal / tb.lu * (tb.sval^2 / 2.0))\n", + " return Qs, bal, Qs_positive, bal_positive, Qpeak, br_crit, Qpeak_ind, Δs\n", + "end" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3", + "metadata": {}, + "outputs": [], + "source": [ + "p = GeneralizedPerturbedEquilibrium.InnerLayer.slayer_parameters(\n", + " n_e=1e19, t_e=1e3, t_i=1e3,\n", + " omega=0.0, omega_e=40, omega_i=-20,\n", + " qval=2.0, sval_r=0.5, bt=2.0, rs=1.0, R0=3.0, mu_i=2.0, zeff=1.0,\n", + " chi_perp=1.0, chi_tor=1.0, m=2, n=1\n", + ")\n", + "p = GeneralizedPerturbedEquilibrium.InnerLayer.SLAYERParameters(\n", + " ising=p.ising,\n", + " m=p.m, n=p.n,\n", + " tau=p.tau, lu=p.lu, c_beta=p.c_beta, D_norm=p.D_norm,\n", + " P_perp=p.P_perp, P_tor=p.P_tor,\n", + " Q_e=2, Q_i=3, iota_e=p.iota_e,\n", + " tauk=p.tauk, tau_r=p.tau_r, delta_n=p.delta_n,\n", + " rs=p.rs, R0=p.R0, bt=p.bt, sval_r=p.sval_r,\n", + " dr_val=p.dr_val, dgeo_val=p.dgeo_val,\n", + " eta=p.eta, d_beta=p.d_beta,\n", + " dc_tmp=p.dc_tmp, dc_type=p.dc_type\n", + ")\n", + "\n", + "tb = TorqueBalance(\n", + " GeneralizedPerturbedEquilibrium.InnerLayer.SLAYERModel(;),\n", + " p,\n", + " 0.5,\n", + " 61.0, #1.0\n", + " p.lu,\n", + " p.sval_r\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "Qs, bal, Qs_positive, bal_positive, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb,Qmin=-2.5, Qmax=0, n=20000)\n", + "\n", + "jxbs = [-imag(1.0 / (d + 1e-2)) for d in Δs]\n", + "T_VISC = [2.0 * tb.P * (tb.Q0 - q) for q in Qs] #(q, jxb) in zip(Qs, jxbs)]\n", + "#br_t = brcrit\n", + "#println(tb.lu, \" \", tb.sval, \" \", br_t, \" \", p.bt, \" \", 1e-2)\n", + "#@printf(\"br_crit = %.5e\\n\", brcrit)\n", + "#T_EM = tb.lu * tb.sval^2/2 * (brcrit)^2 * jxbs\n", + "T_EM = -imag(1.0 ./ (Δs .+ 1e-2)) *brcrit^2*tb.lu/(tb.sval^2/2)\n", + "i = Qpeak_ind\n", + "println(T_VISC[i]/(tb.lu * tb.sval^2/2 * (brcrit)^2 * jxbs[i]))\n", + "println(T_VISC[i] / (tb.lu * tb.sval^2/2 * (brcrit * p.bt)^2 * jxbs[i]))\n", + "println(T_VISC[i] / ( (brcrit / p.bt)^2 * jxbs[i]))\n", + "\n", + "#T_EM ∝ S ξ̂ (br/Bφ)² Im[-Δ̂(Q)⁻¹]\n", + "#T_visc ∝ 2 P (Q0 − Q)\n", + "\n", + "xmi = -2.5\n", + "xma = 0\n", + "\n", + "\"\"\"\n", + "p1 = plot(Qs, imag.(Δs), label=\"Im(Δ)\", lw=2, xlim=(xmi, xma))\n", + "#plot!(p1, Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", + "xlabel!(p1, \"Q\")\n", + "ylabel!(p1, \"Δ\")\n", + "#title!(p1, \"Inner-layer Δ(Q)\")\n", + "\"\"\"\n", + "\n", + "p1 = plot( Qs, T_VISC, label=\"T_V\", lw=2, xlim=(xmi, xma))#,ylim=(-1000,1000))\n", + "plot!(p1, Qs, T_EM, label=\"T_EM\", lw=2)\n", + "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + "xlabel!(p1, \"Q\")\n", + "ylabel!(p1, \"Torque\")\n", + "\n", + "#p2 = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", + "p2 = plot( Qs, T_VISC, label=\"T_V\", lw=2, xlim=(xmi, xma))#,ylim=(0,500))\n", + "plot!(p2, Qs, T_EM, label=\"T_EM\", lw=2)\n", + "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + "xlabel!(p2, \"Q\")\n", + "ylabel!(p2, \"Torque\")\n", + "#title!(p2, \"jxb(Q) = -Im[1/(Δ + δ_n_p)]\")\n", + "\n", + "p3 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2, xlim=(xmi, xma))\n", + "plot!(p3, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", + "ylabel!(p3, \"Torque Balance\")\n", + "#title!(p3, \"2P(Q0-Q)/jxb\")\n", + "xlabel!(p3, \"Q\")\n", + "vline!([Qpeak], label=\"Max Balance\", linestyle=:dash)\n", + "\n", + "#plot(p1, p2, p3, layout=(3,1), size=(800, 1000))\n", + "plot(p3, layout=(1,1), size=(800, 1000))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5", + "metadata": {}, + "outputs": [], + "source": [ + "# compare Q_e to Q of max(bal)\n", + "println(\"-Q_e = \", -p.Q_e, \" Q_i = \", p.Q_i, \" Q_peak = \", Qpeak, \" br_crit = \", brcrit)\n", + "# check if |Qpeak+Q_e| < 1e-2\n", + "println(\"|Qpeak + Q_e| = \", abs(Qpeak + p.Q_e))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6", + "metadata": {}, + "outputs": [], + "source": [ + "# Check torque is balanced\n", + "\n", + "viscous_torque = 2*tb.P*(tb.Q0 - Qpeak)\n", + "electromagnetic_torque = -imag(1.0 / (Δs[Qpeak_ind] + 1e-2)) *brcrit^2*tb.lu/(tb.sval^2/2)\n", + "\n", + "# delta_n_p = 1e-2\n", + "# jxb = -imag(1.0 / (Δ + delta_n_p))\n", + "# bal = 2.0 * tb.P * (tb.Q0 - Q) / jxb\n", + "# br_crit = sqrt(maxbal / tb.lu * (tb.sval^2 / 2.0))\n", + "\n", + "@printf(\"br_crit = %.5e\\n\", brcrit)\n", + "@printf(\"viscous_torque = %.5e\\n\", viscous_torque)\n", + "@printf(\"electromagnetic_torque = %.5e\\n\", electromagnetic_torque)\n", + "@printf(\"ratio = %.10f\\n\", viscous_torque / electromagnetic_torque)" + ] + } + ], + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/src/Tearing/CriticalResonantField/CRF Dev/sample_number.jls b/src/Tearing/CriticalResonantField/CRF Dev/sample_number.jls new file mode 100644 index 0000000000000000000000000000000000000000..c320ccaa9d62b84e8037da421fd24ccf2da49346 GIT binary patch literal 68 ucmXr_@{wa 0.0)\n", - "\n", - " if !any(positive)\n", - " return Qs, bal, NaN, 0.0\n", - " end\n", - " i = argmax(bal)\n", - " Qpeak_ind = i\n", - " Qs_positive = Qs[positive]\n", - " bal_positive = bal[positive]\n", - "\n", - " i = argmax(bal_positive)\n", - " Qpeak = Qs_positive[i]\n", - " \n", - " maxbal = bal_positive[i]\n", - "\n", - " br_crit = sqrt(maxbal / tb.lu * (tb.sval^2 / 2.0))\n", - " return Qs, bal, Qs_positive, bal_positive, Qpeak, br_crit, Qpeak_ind, Δs\n", - "end" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3", - "metadata": {}, - "outputs": [], - "source": [ - "# You can substitute any valid SLAYERParameters you already have.\n", - "# This is just an example skeleton.\n", - "p = GeneralizedPerturbedEquilibrium.InnerLayer.slayer_parameters(\n", - " n_e=1e19, t_e=1e3, t_i=1e3,\n", - " omega=0.0, omega_e=4, omega_i=-2,\n", - " qval=2.0, sval_r=0.5, bt=2.0, rs=1.0, R0=3.0, mu_i=2.0, zeff=1.0,\n", - " chi_perp=1.0, chi_tor=1.0, m=2, n=1\n", - ")\n", - "p2 = GeneralizedPerturbedEquilibrium.InnerLayer.SLAYERParameters(\n", - " ising=p.ising,\n", - " m=p.m, n=p.n,\n", - " tau=p.tau, lu=p.lu, c_beta=p.c_beta, D_norm=p.D_norm,\n", - " P_perp=p.P_perp, P_tor=p.P_tor,\n", - " Q_e=4 / p.tauk, Q_i=-10 / p.tauk, iota_e=p.iota_e,\n", - " tauk=p.tauk, tau_r=p.tau_r, delta_n=p.delta_n,\n", - " rs=p.rs, R0=p.R0, bt=p.bt, sval_r=p.sval_r,\n", - " dr_val=p.dr_val, dgeo_val=p.dgeo_val,\n", - " eta=p.eta, d_beta=p.d_beta,\n", - " dc_tmp=p.dc_tmp, dc_type=p.dc_type\n", - ")\n", - "\n", - "#p = p2\n", - "\n", - "tb = TorqueBalance(\n", - " GeneralizedPerturbedEquilibrium.InnerLayer.SLAYERModel(;),\n", - " p,\n", - " 0.5,\n", - " 1.0,\n", - " p.lu,\n", - " p.sval_r\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4", - "metadata": {}, - "outputs": [], - "source": [ - "#Qs = range(-5.0, 5.0, length=200)\n", - "\n", - "#vals = [torque_balance_value(tb, q) for q in Qs]\n", - "\"\"\"\n", - "n=2000:\n", - "Qpeak = 0.24512256128064033\n", - "maxbal = 0.35873684252530247\n", - "br_crit = 4.668551985584323e-5\n", - "\n", - "n=200 (def):\n", - "Qpeak = 0.25125628140703515\n", - "maxbal = 0.3585219071071706\n", - "br_crit = 4.667153206033017e-5\n", - "\"\"\"\n", - "Qs, bal, Qs_positive, bal_positive, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb)\n", - "\n", - "println(\"Qpeak = \", Qpeak)\n", - "println(\"maxbal = \", maximum(bal_positive))\n", - "println(\"maxbal = \", maximum(bal))\n", - "println(\"br_crit = \", brcrit)\n", - "\n", - "p1 = plot(Qs, bal, lw=2, label=\"balance\")\n", - "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", - "xlabel!(\"Q\")\n", - "ylabel!(\"balance\")\n", - "title!(\"Torque-balance scan\")\n", - "\n", - "p2 = plot(Qs_positive, bal_positive, lw=2, label=\"balance (positive)\")\n", - "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", - "xlabel!(\"Q\")\n", - "ylabel!(\"balance\")\n", - "title!(\"Torque-balance scan\")\n", - "\n", - "plot(p1, p2, layout=(2,1), size=(800, 1000))\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5", - "metadata": {}, - "outputs": [], - "source": [ - "jxbs = [-imag(1.0 / (d + 1e-2)) for d in Δs]\n", - "\n", - "p1 = plot(Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", - "plot!(p1, Qs, imag.(Δs), label=\"Im(Δ)\", lw=2)\n", - "xlabel!(p1, \"Q\")\n", - "ylabel!(p1, \"Δ\")\n", - "title!(p1, \"Inner-layer Δ(Q)\")\n", - "\n", - "p2 = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", - "xlabel!(p2, \"Q\")\n", - "ylabel!(p2, \"jxb\")\n", - "title!(p2, \"jxb(Q) = -Im[1/(Δ + δ_n_p)]\")\n", - "\n", - "p3 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2)\n", - "plot!(p3, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", - "xlabel!(p3, \"Q\")\n", - "ylabel!(p3, \"balance\")\n", - "title!(p3, \"2P(Q0-Q)/jxb\")\n", - "\n", - "plot(p1, p2, p3, layout=(3,1), size=(800, 1000))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6", - "metadata": {}, - "outputs": [], - "source": [ - "Qpk = Qs_positive[argmax(bal_positive)]\n", - "j = findfirst(isequal(Qpk), Qs)\n", - "\n", - "lhs = 2*tb.P*(tb.Q0 - Qpk) / jxbs[j]\n", - "br_ratio = sqrt(lhs / (tb.lu * tb.sval^2 / 2))\n", - "\n", - "rhs = (tb.lu * tb.sval^2 / 2) * br_ratio^2\n", - "\n", - "\n", - "\n", - "println(\"lhs = \", lhs)\n", - "println(\"rhs = \", rhs)\n", - "println(\"lhs/rhs = \", lhs / rhs)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7", - "metadata": {}, - "outputs": [], - "source": [ - "#Δs = [solve_inner(tb.model, tb.params, ComplexF64(q)).tearing for q in Qs]\n", - "jxbs = [-imag(1.0 / (d + tb.delta_n_p)) for d in Δs]\n", - "T_VISC = [2.0 * tb.P * (tb.Q0 - q) for (q, jxb) in zip(Qs, jxbs)]\n", - "br_t = brcrit\n", - "println(tb.lu, \" \", tb.sval, \" \", br_t, \" \", p.bt, \" \", tb.delta_n_p)\n", - "T_EM = tb.lu * tb.sval^2/2 * (brcrit)^2 * jxbs\n", - "i = Qpeak_ind\n", - "println(T_VISC[i]/(tb.lu * tb.sval^2/2 * (brcrit)^2 * jxbs[i]))\n", - "println(T_VISC[i] / (tb.lu * tb.sval^2/2 * (brcrit * p.bt)^2 * jxbs[i]))\n", - "println(T_VISC[i] / ( (brcrit / p.bt)^2 * jxbs[i]))\n", - "\n", - "#T_EM ∝ S ξ̂ (br/Bφ)² Im[-Δ̂(Q)⁻¹]\n", - "#T_visc ∝ 2 P (Q0 − Q)\n", - "\n", - "p1 = plot(Qs, imag.(Δs), label=\"Im(Δ)\", lw=2)\n", - "#plot!(p1, Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", - "xlabel!(p1, \"Q\")\n", - "ylabel!(p1, \"Δ\")\n", - "title!(p1, \"Inner-layer Δ(Q)\")\n", - "\n", - "p2 = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", - "plot!(p2, Qs, T_VISC, label=\"2P(Q0-Q)\", lw=2)\n", - "plot!(p2, Qs, T_EM, label=\"T_EM\", lw=2)\n", - "xlabel!(p2, \"Q\")\n", - "ylabel!(p2, \"jxb\")\n", - "title!(p2, \"jxb(Q) = -Im[1/(Δ + δ_n_p)]\")\n", - "\n", - "p3 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2)\n", - "plot!(p3, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", - "xlabel!(p3, \"Q\")\n", - "ylabel!(p3, \"balance\")\n", - "title!(p3, \"2P(Q0-Q)/jxb\")\n", - "\n", - "plot(p1, p2, p3, layout=(3,1), size=(800, 1000))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8", - "metadata": {}, - "outputs": [], - "source": [ - "# Recreate Cihan's plot:\n", - "\n", - "using Plots\n", - "using DataInterpolations\n", - "\n", - "default(\n", - " fontfamily=\"Georgia\",\n", - " grid=false,\n", - " linewidth=2,\n", - " guidefontsize=26,\n", - " tickfontsize=18,\n", - " titlefontsize=30,\n", - " legendfontsize=18,\n", - " size=(1200, 800),\n", - " dpi=150\n", - ")\n", - "\n", - "# Build the critical boundary bcrit(Q0)\n", - "Q0_scan = range(-1.0, 4.5; length=80)\n", - "bcrit_curve = Float64[]\n", - "\n", - "for Q0 in Q0_scan\n", - " tbQ = TorqueBalance(\n", - " tb.model,\n", - " tb.params,\n", - " Float64(Q0),\n", - " tb.P,\n", - " tb.delta_n_p,\n", - " tb.lu,\n", - " tb.sval\n", - " )\n", - "\n", - " Qs, bal, Qs_pos, bal_pos, Qpeak, brcrit, Qpeak_ind, Δs =\n", - " torque_balance_scan(tbQ; Qmin=-10.0, Qmax=10.0, n=250)\n", - "\n", - " if isempty(bal_pos) || !all(isfinite.(bal_pos)) || maximum(bal_pos) <= 0\n", - " push!(bcrit_curve, NaN)\n", - " else\n", - " push!(bcrit_curve, brcrit)\n", - " end\n", - "end\n", - "\n", - "ok = isfinite.(bcrit_curve)\n", - "Q0_plot = Q0_scan[ok]\n", - "bcrit_plot = bcrit_curve[ok]\n", - "\n", - "perm = sortperm(Q0_plot)\n", - "Q0_plot = Q0_plot[perm]\n", - "bcrit_plot = bcrit_plot[perm]\n", - "\n", - "# Interpolate the boundary: bcrit = f(Q0)\n", - "curve_itp = LinearInterpolation(bcrit_plot, Q0_plot)\n", - "\n", - "# Full phase-box bounds\n", - "x0 = minimum(bcrit_plot) * 0.8\n", - "x1 = maximum(bcrit_plot) * 1.2\n", - "y0 = minimum(Q0_plot)\n", - "y1 = maximum(Q0_plot)\n", - "\n", - "xvals = range(x0, x1; length=350)\n", - "yvals = range(y0, y1; length=350)\n", - "\n", - "locked_mask = zeros(Float64, length(yvals), length(xvals))\n", - "for iy in eachindex(yvals)\n", - " y = yvals[iy]\n", - " for ix in eachindex(xvals)\n", - " x = xvals[ix]\n", - " # locked when bcrit exceeds the boundary for that Q0\n", - " locked_mask[iy, ix] = x >= curve_itp(y) ? 1.0 : 0.0\n", - " end\n", - "end\n", - "\n", - "p = contourf(\n", - " xvals, yvals, locked_mask',\n", - " levels=[-0.5, 0.5, 1.5],\n", - " c=[:navy, :firebrick],\n", - " colorbar=false,\n", - " xlabel=\"b_crit\",\n", - " ylabel=\"Q_0\",\n", - " title=\"Locked / unlocked region\",\n", - " framestyle=:box,\n", - " xlims=(x0, x1),\n", - " ylims=(y0, y1),\n", - " legend=false\n", - ")\n", - "\n", - "# Critical boundary\n", - "plot!(p, bcrit_plot, Q0_plot; lw=3, color=:black, label=\"critical boundary\")\n", - "\n", - "# Critical point\n", - "cp_idx = argmax(bcrit_plot)\n", - "cp_x = bcrit_plot[cp_idx]\n", - "cp_y = Q0_plot[cp_idx]\n", - "scatter!(p, [cp_x], [cp_y]; color=:gold, marker=:star5, ms=12, label=\"critical point\")\n", - "\n", - "# Single legend block with one entry per category\n", - "plot!(p, [NaN], [NaN]; color=:firebrick, lw=4, label=\"locked\")\n", - "plot!(p, [NaN], [NaN]; color=:navy, lw=4, label=\"unlocked\")\n", - "plot!(p, [NaN], [NaN]; color=:black, lw=3, label=\"critical boundary\")\n", - "scatter!(p, [NaN], [NaN]; color=:gold, marker=:star5, ms=12, label=\"critical point\")\n", - "\n", - "plot!(p; legend=:topright)\n", - "\n", - "display(p)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "10", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/src/Tearing/Runner/HDF5Output.jl b/src/Tearing/Runner/HDF5Output.jl index 02c3f5da9..006f2d079 100644 --- a/src/Tearing/Runner/HDF5Output.jl +++ b/src/Tearing/Runner/HDF5Output.jl @@ -82,6 +82,13 @@ function write_critical_resonant_field_hdf5!(parent::Union{HDF5.File,HDF5.Group} sg["balance_positive"] = d.balance_positive sg["Qpeak"] = d.Qpeak sg["br_crit"] = d.br_crit + + # Save inputs for analysis in post + for field in (:Q0, :P, :lu, :sval, :m, :n) + if field in keys(d) + sg[String(field)] = getfield(d, field) + end + end end end diff --git a/src/Tearing/Runner/run_slayer.jl b/src/Tearing/Runner/run_slayer.jl index 5c92691f5..3d51d4a11 100644 --- a/src/Tearing/Runner/run_slayer.jl +++ b/src/Tearing/Runner/run_slayer.jl @@ -472,10 +472,11 @@ end function run_critical_resonant_field(equil, intr, ctrl; dir_path="./", slayer_result=nothing) ctrl.enabled || return empty_critical_resonant_field_result() + profiles = load_kinetic_profiles(joinpath(dir_path, ctrl.profile_file)) + params = if slayer_result !== nothing && slayer_result.enabled && !isempty(slayer_result.params) slayer_result.params else - profiles = load_kinetic_profiles(joinpath(dir_path, ctrl.profile_file)) build_slayer_inputs(equil, intr.sing, profiles) end @@ -490,8 +491,9 @@ function run_critical_resonant_field(equil, intr, ctrl; dir_path="./", slayer_re scan_data = NamedTuple[] for (isurf, p) in enumerate(params) - # Fill in the actual per-surface drive from your model - Q0_here = 0.5 + psi_here = intr.sing[isurf].psifac + omega_here = profiles(psi_here).omega + Q0_here = p.tauk * omega_here P_here = 1.0 tb = TorqueBalance( @@ -512,21 +514,25 @@ function run_critical_resonant_field(equil, intr, ctrl; dir_path="./", slayer_re push!(Q0_vec, Q0_here) push!(P_vec, P_here) - if ctrl.store_scan - push!( - scan_data, - ( - surface=isurf, - Q=collect(Qs), - balance=collect(bal), - delta=collect(Δs), - Q_positive=collect(Qs_positive), - balance_positive=collect(bal_positive), - Qpeak=Qpeak, - br_crit=br_crit - ) - ) - end + scan_entry = ( + surface=isurf, + Q=collect(Qs), + balance=collect(bal), + delta=collect(Δs), + Q_positive=collect(Qs_positive), + balance_positive=collect(bal_positive), + Qpeak=Qpeak, + br_crit=br_crit, + Q0=Q0_here, + P=P_here, + lu=p.lu, + sval=p.sval_r, + m=p.m, + n=p.n, + params=p + ) + push!(scan_data, scan_entry) + end return CriticalResonantFieldResult( From 6f4a356483082f90baed0df5f3c45cd2bd9b08af Mon Sep 17 00:00:00 2001 From: ebursch <76970916+ebursch@users.noreply.github.com> Date: Wed, 19 Aug 2026 22:04:23 -0400 Subject: [PATCH 6/9] WIP - Minimal working version --- examples/DIIID-like_SLAYER_example/gpec.toml | 8 +- .../DIIID-like_SLAYER_example/slayer_ex.ipynb | 86 +++++- .../CRF Dev/P_eta_calc.ipynb | 279 ++++++++++++++++++ .../CRF Dev/bcrit_dev.ipynb | 4 +- .../CRF Dev/pole_testing.ipynb | 193 +++++++++++- .../CriticalResonantField/TorqueBalance.jl | 86 +++++- src/Tearing/Runner/Control.jl | 80 ++--- src/Tearing/Runner/HDF5Output.jl | 11 +- src/Tearing/Runner/Result.jl | 77 ++--- src/Tearing/Runner/Runner.jl | 1 + src/Tearing/Runner/run_slayer.jl | 225 ++++++++------ 11 files changed, 839 insertions(+), 211 deletions(-) create mode 100644 src/Tearing/CriticalResonantField/CRF Dev/P_eta_calc.ipynb diff --git a/examples/DIIID-like_SLAYER_example/gpec.toml b/examples/DIIID-like_SLAYER_example/gpec.toml index d5dfe09c3..618372d02 100644 --- a/examples/DIIID-like_SLAYER_example/gpec.toml +++ b/examples/DIIID-like_SLAYER_example/gpec.toml @@ -30,7 +30,7 @@ equal_arc_wall = true # Equal arc length distribution of nodes on wall [ForceFreeStates] force_termination = true # Run FFS + SLAYER, skip PerturbedEquilibrium -local_stability_flag = true # Perform local stability analysis (Mercier and ballooning) across the ψ profile +local_stability_flag = false # Perform local stability analysis (Mercier and ballooning) across the ψ profile vac_flag = true # Compute plasma, vacuum, and total energies for free-boundary modes psiedge = 0.99 # Edge dW scan band: diagnostic dW(ψ) computed for ψ ∈ [psiedge, psilim]; integration domain set by qhigh / psihigh / dmlim @@ -87,11 +87,11 @@ Q_im_range = [-0.5, 3.0] # Scan box in the normalized Q plane, Im(Q) axis nre = 41 # Grid resolution along the Re(Q) axis nim = 31 # Grid resolution along the Im(Q) axis -[CriticalResonantField] +[SLAYER.CriticalResonantField] # CriticalResonantField used to find the critical resonant field sufficent for tearing onset at each rational surface. enabled = true # Run CriticalResonantField analysis -inner_model = "slayer_fitzpatrick" # Inner-layer Δ(Q) model: "slayer_fitzpatrick", "ggj_shooting", or "ggj_galerkin" Qmin = -10 # Minimum rotation scanned Qmax = 10 # Maximum rotation scanned n = 200 # Number of rotation points scanned -profile_file = "../DIIID-like_ideal_example/TkMkr_D3Dlike_Hmode_kinetic.h5" # Kinetic-profile file (relative to the run dir), required when SLAYER is enabled +angular_momentum_diffusivity = [1.0,1.0,1.0,1.0,1.0,1.0] # Toroidal momentum diffusivity (if nothing, falls back on chi_perp ~ chi_e, electron thermal diffusivity) +store_scan = true # Per surface torque and inner layer quantities diff --git a/examples/DIIID-like_SLAYER_example/slayer_ex.ipynb b/examples/DIIID-like_SLAYER_example/slayer_ex.ipynb index 709891273..710608340 100644 --- a/examples/DIIID-like_SLAYER_example/slayer_ex.ipynb +++ b/examples/DIIID-like_SLAYER_example/slayer_ex.ipynb @@ -134,6 +134,90 @@ "id": "6", "metadata": {}, "outputs": [], + "source": [ + "# print all P values\n", + "println(\"\\nP values for each surface in the scan:\")\n", + "h5open(h5path, \"r\") do file\n", + " for i in 1:6\n", + " ss = \"surface_$i\"\n", + " if haskey(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"], ss)\n", + " P = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][ss][\"P\"])\n", + " println(\"Surface $i: P = $(join([@sprintf(\"%.2e\", x) for x in P], \" \"))\")\n", + " else\n", + " println(\"Surface $i: No data found.\")\n", + " end\n", + " end\n", + "end\n", + "# want to print chi_tor for each surface in the scan, need to use P = (4π * 1e-7) .* abs.(chi_sel) ./ η_neo, so chi_sel = P * η_neo / (4π * 1e-7)\n", + "println(\"\\nchi_tor values for each surface in the scan:\")\n", + "h5open(h5path, \"r\") do file\n", + " for i in 1:6\n", + " ss = \"surface_$i\"\n", + " if haskey(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"], ss)\n", + " P = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][ss][\"P\"])\n", + " η_neo = read(file[\"Tearing\"][\"PerSurface\"][\"eta\"])\n", + " chi_tor = P .* η_neo[i] ./ (4π * 1e-7)\n", + " println(\"Surface $i: chi_tor = $(join([@sprintf(\"%.2e\", x) for x in chi_tor], \" \"))\") \n", + " else\n", + " println(\"Surface $i: No data found.\")\n", + " end\n", + " end\n", + "end" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7", + "metadata": {}, + "outputs": [], + "source": [ + "# plot jxb vs Qs for surface 1\n", + "# jxbs = [-imag(1.0 / (d + 1e-2)) for d in Δs]\n", + "surface_num = 2\n", + "h5open(h5path, \"r\") do file\n", + " Δs = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"delta\"])\n", + " Qs = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"Q\"])\n", + " bal = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"balance\"])\n", + " jxbs = [-imag(1.0 / (d + 1e-2)) for d in Δs]\n", + " aplot = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", + " xlabel!(\"Q\")\n", + " ylabel!(\"jxb\")\n", + " title!(\"jxb vs Q for surface $(surface_num)\")\n", + " println(\"max of balance: \", maximum(bal))\n", + " println(\"max of jxb: \", maximum(jxbs))\n", + " println(\"bcrit: \", read(file[\"Tearing\"][\"CriticalResonantField\"][\"br_crit\"]))\n", + " println(\"Qpeak: \", read(file[\"Tearing\"][\"CriticalResonantField\"][\"Qpeak\"]))\n", + " println(\"Q_e: \", read(file[\"Tearing\"][\"PerSurface\"][\"Q_e\"]))\n", + " # plot balance vs q with bcrit as vertical line\n", + " p2 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2)\n", + " plot!(p2, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", + " xlabel!(p2, \"Q\")\n", + " ylabel!(p2, \"balance\")\n", + " title!(p2, \"2P(Q0-Q)/jxb - surface $(surface_num)\")\n", + " vline!(p2, [read(file[\"Tearing\"][\"CriticalResonantField\"][\"br_crit\"])], label=\"bcrit\", lw=2, lc=:red)\n", + " # add Q_e as vertical line\n", + " vline!(p2, [read(file[\"Tearing\"][\"PerSurface\"][\"Q_e\"])[surface_num]], label=\"Q_e\", lw=2, lc=:green)\n", + " vline!(p2, [read(file[\"Tearing\"][\"PerSurface\"][\"Q_i\"])[surface_num]], label=\"Q_i\", lw=2, lc=:blue)\n", + "\n", + " display(aplot)\n", + " display(p2)\n", + "\n", + "end\n", + "\n", + "\"\"\"\n", + "Local maxima indices: [104, 103] with values: [80.15320925995013, 79.66428209429431] and corresponding Qs: [0.35175879396984927, 0.25125628140703515] closest Q to Q_e: -0.35175879396984927 closest Q to Q_i: 0.35175879396984927\n", + "Warning: The first local maximum may correspond to an electron or ion diamagnetic resonance. Selecting the second local maximum instead.\n", + "Selected local maximum index: 103 with value: 79.66428209429431 and corresponding Q: 0.25125628140703515\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8", + "metadata": {}, + "outputs": [], "source": [ "# Plot bcrit vs q surface\n", "\n", @@ -156,7 +240,7 @@ { "cell_type": "code", "execution_count": null, - "id": "7", + "id": "9", "metadata": {}, "outputs": [], "source": [ diff --git a/src/Tearing/CriticalResonantField/CRF Dev/P_eta_calc.ipynb b/src/Tearing/CriticalResonantField/CRF Dev/P_eta_calc.ipynb new file mode 100644 index 000000000..0639317bd --- /dev/null +++ b/src/Tearing/CriticalResonantField/CRF Dev/P_eta_calc.ipynb @@ -0,0 +1,279 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "0", + "metadata": {}, + "outputs": [], + "source": [ + "using Pkg\n", + "Pkg.activate(\"/Users/bursche/Documents/GitHub/JPEC_BCRIT\")\n", + "Base.active_project()\n", + "\n", + "using Plots\n", + "using Printf" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1", + "metadata": {}, + "outputs": [], + "source": [ + "# Minimal Julia implementation of the `neo_2021` branch.\n", + "\n", + "# Inputs:\n", + "# Te : electron temperature [eV]\n", + "# ne : electron density [m^-3]\n", + "# Ti : ion temperature [eV]\n", + "# q : safety factor\n", + "# eps : inverse aspect ratio\n", + "# R : major radius [m]\n", + "# fT : trapped-particle fraction\n", + "# Zeff : effective charge\n", + "\n", + "# Output:\n", + "# σ_spitzer : Spitzer conductivity [1/(Ω m)]\n", + "# σ_neo : Redl 2021 neoclassical conductivity [1/(Ω m)]\n", + "\n", + "# All inputs can be scalars or arrays of the same size.\n", + "\n", + "function neoclassical_conductivity(\n", + " Te, ne, Ti, q, eps, R, fT, Zeff;\n", + " version = :neo_2021,\n", + ")\n", + "\n", + " # Coulomb logarithms\n", + " lnΛe = 23.5 .-\n", + " log.(sqrt.(ne ./ 1e6) .* Te.^(-5/4)) .-\n", + " sqrt.(1e-5 .+ (log.(Te) .- 2).^2 ./ 16)\n", + "\n", + " # Ion density.\n", + " #\n", + " # For the simple D + C model used in the original code:\n", + " # n_i = n_main + n_imp\n", + " #\n", + " # If only Zeff is supplied, the original function uses\n", + " # n_i = ne / Zeff\n", + " ni = ne ./ Zeff\n", + "\n", + " # With only Zeff available, Zdom = 1, giving\n", + " Zdom = 1.0\n", + "\n", + " # Average ion charge\n", + " Zavg = ne ./ ni\n", + "\n", + " # Koh effective ion charge\n", + " Zion = (Zdom^2 .* Zavg .* Zeff).^(1/4)\n", + "\n", + " # Ion Coulomb logarithm\n", + " lnΛi = 30.0 .-\n", + " log.(Zion.^3 .* sqrt.(ni) ./ Ti.^1.5)\n", + "\n", + " # Prevent pathological negative electron Coulomb logarithms\n", + " lnΛe_min = minimum(lnΛe[lnΛe .> 0])\n", + " lnΛe = max.(lnΛe, lnΛe_min)\n", + "\n", + " # Avoid eps = 0\n", + " eps_nz = copy(eps)\n", + " if any(eps .== 0)\n", + " eps_nz[eps .== 0] .= minimum(eps[eps .!= 0])\n", + " end\n", + "\n", + " # Electron collisionality, Eq. 18b\n", + " νe_star = 6.921e-18 .* abs.(q) .* R .* ne .* Zeff .* lnΛe ./\n", + " (Te.^2 .* eps_nz.^1.5)\n", + "\n", + " # Ion collisionality, Eq. 18c\n", + " νi_star = 4.90e-18 .* abs.(q) .* R .* ni .* Zion.^4 .* lnΛi ./\n", + " (Ti.^2 .* eps_nz.^1.5)\n", + "\n", + " # Sauter Eq. 18a\n", + " NZ(Z) = 0.58 + 0.74 ./ (0.76 + Z)\n", + "\n", + " σ_spitzer = 1.9012e4 .* Te.^1.5 ./\n", + " (Zeff .* NZ(Zeff) .* lnΛe)\n", + "\n", + " # Redl 2021, Eq. 18\n", + " f33teff = fT ./ (\n", + " 1 .+\n", + " 0.25 .* (1 .- 0.7 .* fT) .* sqrt.(νe_star) .*\n", + " (1 .+ 0.45 .* sqrt.(Zeff .- 1)) .+\n", + " 0.61 .* (1 .- 0.41 .* fT) .* νe_star ./ sqrt.(Zeff)\n", + " )\n", + "\n", + " # Redl 2021, Eq. 17\n", + " F33 = 1 .-\n", + " (1 .+ 0.21 ./ Zeff) .* f33teff .+\n", + " 0.54 ./ Zeff .* f33teff.^2 .-\n", + " 0.33 ./ Zeff .* f33teff.^3\n", + "\n", + " σ_neo = σ_spitzer .* F33\n", + "\n", + " return σ_neo, σ_spitzer\n", + "end" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2", + "metadata": {}, + "outputs": [], + "source": [ + "function calc_resistivity_P(chi, ne, Te, Zeff, q, eps, R, fT, volume;\n", + " model=:neoclassical)\n", + " cond = neoclassical_conductivity(\n", + " Te=Te,\n", + " ne=ne,\n", + " Ti=Te,\n", + " Zeff=Zeff,\n", + " q=q,\n", + " eps=eps,\n", + " R=R,\n", + " fT=fT,\n", + " volume=volume,\n", + " version=:neo_2021,\n", + " )\n", + "\n", + " σ = model == :neoclassical ?\n", + " cond.neoclassical_conductivity :\n", + " cond.spitzer_conductivity\n", + "\n", + " η = 1 ./ σ\n", + " P = (4π * 1e-7) .* abs.(chi) ./ η\n", + "\n", + " return η, P\n", + "end" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3", + "metadata": {}, + "outputs": [], + "source": [ + "σ_neo, σ_spitzer = neoclassical_conductivity(\n", + " Te_eV,\n", + " ne_sel,\n", + " Te_eV, # Ti = Te\n", + " qsing,\n", + " eps_sel,\n", + " R_sel,\n", + " fT_sel;\n", + " Zeff=zeff_sel,\n", + ")\n", + "\n", + "η_neo = 1.0 ./ σ_neo\n", + "η_spitzer = 1.0 ./ σ_spitzer\n", + "\n", + "P = (4π * 1e-7) .* abs.(chi_sel) ./ η_neo" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4", + "metadata": {}, + "outputs": [], + "source": [ + "σ_neo, σ_spitzer = neoclassical_conductivity(\n", + " 106.211805100300, # Te [eV]\n", + " 1.005827348013049e19, # ne [m^-3]\n", + " 106.211805100300, # Ti [eV]\n", + " 6.00000000000048, # q\n", + " 0.771873939341347 / 1.74333594120074, # eps = rs / R0\n", + " 1.74333594120074, # R [m]\n", + " 1, #fT; # trapped fraction\n", + " 1.80427095488192, # Zeff\n", + ")\n", + "\n", + "η_neo = 1.0 ./ σ_neo\n", + "η_spitzer = 1.0 ./ σ_spitzer\n", + "\n", + "chi_sel = 1\n", + "\n", + "P = (4π * 1e-7) .* abs.(chi_sel) ./ η_neo" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5", + "metadata": {}, + "outputs": [], + "source": [ + "using LinearAlgebra # or relevant module providing neoclassical_conductivity\n", + "\n", + "# --- Set 1 Inputs (5 radial points) ---\n", + "Te_eV = [718.04269217, 342.58020426, 188.39435197, 95.70267912, 44.04668565] # Te and Ti [eV]\n", + "ne_sel = [1.98796958e19, 1.80371630e19, 1.55527262e19, 1.23649097e19, 8.97867646e18] # ne [m^-3]\n", + "zeff_sel = [1.65619282, 1.64427584, 1.58198407, 1.55990923, 1.68572562] # Zeff\n", + "qsing = [2.0, 3.0, 4.0, 5.0, 6.0] # q\n", + "eps_sel = [0.22284171, 0.28956909, 0.32302672, 0.34432513, 0.35141583] # eps = r/R\n", + "R_sel = [1.72151657, 1.70693349, 1.69832026, 1.69192129, 1.68947514] # R [m]\n", + "fT_sel = [0.6127298, 0.66890766, 0.68553652, 0.68355803, 0.67414449] # Trapped fraction fT\n", + "\n", + "# Reference values from Python NCLASS run (for validation)\n", + "py_neo = [7683580.66632273, 3011088.07938057, 1644303.89021149, 782055.27991453, 274193.4323623]\n", + "py_spitzer = [16324797.88300323, 5666135.22162908, 2468477.31865855, 941040.7938515, 290205.76181926]\n", + "\n", + "# --- Run Neoclassical Conductivity in Julia ---\n", + "# Broadcasting across all 5 radial positions:\n", + "σ_neo, σ_spitzer = neoclassical_conductivity.(\n", + " Te_eV, # Te [eV]\n", + " ne_sel, # ne [m^-3]\n", + " Te_eV, # Ti [eV] (assumed Ti = Te)\n", + " qsing, # q\n", + " eps_sel, # eps\n", + " R_sel, # R [m]\n", + " fT_sel, # trapped fraction fT\n", + " zeff_sel # Zeff\n", + ")\n", + "\n", + "# Collect tuple outputs into a vector of tuples\n", + "results = [\n", + " neoclassical_conductivity(\n", + " Te_eV[i], ne_sel[i], Te_eV[i], qsing[i], \n", + " eps_sel[i], R_sel[i], fT_sel[i], zeff_sel[i]\n", + " ) for i in 1:length(Te_eV)\n", + "]\n", + "\n", + "# Extract σ_neo (1st element) and σ_spitzer (2nd element)\n", + "σ_neo = getindex.(results, 1)\n", + "σ_spitzer = getindex.(results, 2)\n", + "\n", + "η_neo = 1.0 ./ σ_neo\n", + "η_spitzer = 1.0 ./ σ_spitzer\n", + "\n", + "chi_sel = 1\n", + "P = (4π * 1e-7) .* abs.(chi_sel) ./ η_neo\n", + "\n", + "\n", + "# --- Comparison Printouts ---\n", + "println(\"=== Neoclassical Conductivity Comparison ===\")\n", + "for i in 1:length(Te_eV)\n", + " println(\"Point $i (q=$(qsing[i])):\")\n", + " println(\" Julia σ_neo : \", σ_neo[i])\n", + " println(\" Python σ_neo : \", py_neo[i])\n", + " println(\" Julia σ_spitzer : \", σ_spitzer[i])\n", + " println(\" Python σ_spitzer: \", py_spitzer[i])\n", + " println(\" P (magnetic diff): \", P[i])\n", + " println()\n", + "end" + ] + } + ], + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/src/Tearing/CriticalResonantField/CRF Dev/bcrit_dev.ipynb b/src/Tearing/CriticalResonantField/CRF Dev/bcrit_dev.ipynb index 528ca4934..5f9dfac2a 100644 --- a/src/Tearing/CriticalResonantField/CRF Dev/bcrit_dev.ipynb +++ b/src/Tearing/CriticalResonantField/CRF Dev/bcrit_dev.ipynb @@ -132,7 +132,7 @@ " GeneralizedPerturbedEquilibrium.InnerLayer.SLAYERModel(;),\n", " p,\n", " 0.5,\n", - " 61.0, #1.0\n", + " p.P_tor,\n", " p.lu,\n", " p.sval_r\n", ")" @@ -162,7 +162,7 @@ "Qmi = -10\n", "Qma = 10\n", "\n", - "Qs, bal, Qs_positive, bal_positive, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb,Qmin=Qmi, Qmax=Qma, n=10000)\n", + "Qs, bal, Qs_positive, bal_positive, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb,Qmin=Qmi, Qmax=Qma, n=100)\n", "\n", "println(\"Qpeak = \", Qpeak)\n", "println(\"maxbal = \", maximum(bal_positive))\n", diff --git a/src/Tearing/CriticalResonantField/CRF Dev/pole_testing.ipynb b/src/Tearing/CriticalResonantField/CRF Dev/pole_testing.ipynb index 329e9dd53..d7f16a2b4 100644 --- a/src/Tearing/CriticalResonantField/CRF Dev/pole_testing.ipynb +++ b/src/Tearing/CriticalResonantField/CRF Dev/pole_testing.ipynb @@ -61,30 +61,81 @@ " return 2.0 * tb.P * (tb.Q0 - Q) / jxb, Δ\n", "end\n", "\n", - "function torque_balance_scan(tb; Qmin=-10.0, Qmax=10.0, n=200)\n", + "function torque_balance_scan(tb; Qmin=-10.0, Qmax=10.0, n=20000)\n", " Qs = range(Qmin, Qmax; length=n)\n", " torque_out = [torque_balance_value(tb, q) for q in Qs]\n", " bal = [x[1] for x in torque_out]\n", " Δs = [x[2] for x in torque_out]\n", - " #bal = [torque_balance_value(tb, q) for q in Qs]\n", " positive = isfinite.(bal) .& (bal .> 0.0)\n", "\n", " if !any(positive)\n", - " return Qs, bal, NaN, NaN, 0.0, NaN, NaN, Δs\n", + " @warn \"No positive torque balance found in the specified range. Try increasing the number of Q samples scanned or adjusting the range.\"\n", + " return Qs, bal, NaN, NaN, NaN, Δs\n", " end\n", "\n", - " i = argmax(bal)\n", - " Qpeak_ind = i\n", - " Qs_positive = Qs[positive]\n", - " bal_positive = bal[positive]\n", + " # Find the highest point, then remove candidates within ΔQ of it.\n", "\n", + " idx_maxima = findall(isfinite.(bal) .& (bal .> 0))\n", + " sort!(idx_maxima, by=i -> bal[i], rev=true)\n", + " selected = Int[]\n", + " min_ΔQ = 0.001 * abs(Qmax - Qmin)\n", "\n", + " for i in idx_maxima\n", + " if all(abs(Qs[i] - Qs[j]) > min_ΔQ for j in selected)\n", + " push!(selected, i)\n", + " end\n", + " length(selected) == 2 && break\n", + " end\n", + "\n", + " if isempty(selected)\n", + " @warn \"No usable positive torque-balance maximum found. Try increasing the number of Q samples scanned or adjusting the range.\"\n", + " return Qs, bal, NaN, NaN, NaN, Δs\n", + " end\n", + "\n", + " idx_maxima = selected\n", + "\n", + "\n", + " # Find all local maxima in the positive region\n", + " #idx_positive = findall(positive)\n", + " #idx_maxima = idx_positive[partialsortperm(bal[idx_positive], 1:min(2, length(idx_positive)); rev=true)]\n", + " maxima = bal[idx_maxima]\n", + " Qs_maxima = Qs[idx_maxima]\n", + " # find index, q val and bal val of the q closest to Q_e\n", + " idx_closest_Q_e = argmin(abs.(Qs .+ tb.params.Q_e)) # + Q_e since Q_e = -omega_e * Qconv\n", + " q_closest_Q_e = Qs[idx_closest_Q_e]\n", + " bal_closest_Q_e = bal[idx_closest_Q_e]\n", + "\n", + " # find index, q val and bal val of the q closest to Q_i\n", + " idx_closest_Q_i = argmin(abs.(Qs .+ tb.params.Q_i)) # + Q_i since Q_i = -omega_i * Qconv\n", + " q_closest_Q_i = Qs[idx_closest_Q_i]\n", + " bal_closest_Q_i = bal[idx_closest_Q_i]\n", " \n", - " Qpeak = Qs_positive[i]\n", - " maxbal = bal_positive[i]\n", + " println(\"Local maxima indices: \", idx_maxima, \" with values: \", maxima, \" and corresponding Qs: \", Qs_maxima, \" closest Q to Q_e: \", q_closest_Q_e, \" closest Q to Q_i: \", q_closest_Q_i)\n", + " # check if 1st q_maxima is same as Q_e or Q_i from p\n", + " if idx_maxima[1] == idx_closest_Q_e || idx_maxima[1] == idx_closest_Q_i\n", + " if length(idx_maxima) < 2\n", + " @warn \"The first local maximum corresponds to a pole from Q_e or Q_i, but there is no second local maximum to select. Try increasing the number of Q samples scanned or adjusting the range.\"\n", + " return Qs, bal, NaN, NaN, NaN, Δs\n", + " end\n", + " println(\"Warning: The first local maximum may correspond to an electron or ion diamagnetic resonance. Selecting the second local maximum instead.\")\n", + " if idx_maxima[2] == idx_closest_Q_e || idx_maxima[2] == idx_closest_Q_i\n", + " @warn \"Both the first and second local maxima correspond to poles from Q_e or Q_i. Unable to select a valid local maximum. Try increasing the number of Q samples scanned or adjusting the range.\"\n", + " return Qs, bal, NaN, NaN, NaN, Δs\n", + " end\n", + " idx_maximum = idx_maxima[2]\n", + " maximum = bal[idx_maximum]\n", + " Qmaximum = Qs[idx_maximum]\n", + " else\n", + " idx_maximum = idx_maxima[1]\n", + " maximum = bal[idx_maximum]\n", + " Qmaximum = Qs[idx_maximum]\n", + " end\n", + "\n", + " println(\"Selected local maximum index: \", idx_maximum, \" with value: \", maximum, \" and corresponding Q: \", Qmaximum)\n", "\n", - " br_crit = sqrt(maxbal / tb.lu * (tb.sval^2 / 2.0))\n", - " return Qs, bal, Qs_positive, bal_positive, Qpeak, br_crit, Qpeak_ind, Δs\n", + " br_crit = sqrt(maximum / tb.lu * (tb.sval^2 / 2.0))\n", + "\n", + " return Qs, bal, Qmaximum, br_crit, idx_maximum, Δs\n", "end" ] }, @@ -131,9 +182,97 @@ "metadata": {}, "outputs": [], "source": [ + "Qs, bal, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb,Qmin=-2.5, Qmax=0, n=200000)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5", + "metadata": {}, + "outputs": [], + "source": [ + "Qmax = 10\n", + "Qmin = -10\n", + "positive = isfinite.(bal) .& (bal .> 0.0)\n", + "\n", + "if !any(positive)\n", + " @warn \"No positive torque balance found in the specified range. Try increasing the number of Q samples scanned or adjusting the range.\"\n", + " return Qs, bal, NaN, NaN, NaN, Δs\n", + "end\n", + "\n", + "# Find the highest point, then remove candidates within ΔQ of it.\n", + "\n", + "idx_maxima = findall(isfinite.(bal) .& (bal .> 0))\n", + "sort!(idx_maxima, by=i -> bal[i], rev=true)\n", + "selected = Int[]\n", + "min_ΔQ = 0.001 * abs(Qmax - Qmin)\n", + "\n", + "for i in idx_maxima\n", + " if all(abs(Qs[i] - Qs[j]) > min_ΔQ for j in selected)\n", + " push!(selected, i)\n", + " end\n", + " length(selected) == 2 && break\n", + "end\n", + "\n", + "if isempty(selected)\n", + " @warn \"No usable positive torque-balance maximum found. Try increasing the number of Q samples scanned or adjusting the range.\"\n", + " return Qs, bal, NaN, NaN, NaN, Δs\n", + "end\n", "\n", - "Qs, bal, Qs_positive, bal_positive, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb,Qmin=-2.5, Qmax=0, n=20000)\n", + "idx_maxima = selected\n", "\n", + "\n", + "# Find all local maxima in the positive region\n", + "#idx_positive = findall(positive)\n", + "#idx_maxima = idx_positive[partialsortperm(bal[idx_positive], 1:min(2, length(idx_positive)); rev=true)]\n", + "maxima = bal[idx_maxima]\n", + "Qs_maxima = Qs[idx_maxima]\n", + "# find index, q val and bal val of the q closest to Q_e\n", + "idx_closest_Q_e = argmin(abs.(Qs .+ tb.params.Q_e)) # + Q_e since Q_e = -omega_e * Qconv\n", + "q_closest_Q_e = Qs[idx_closest_Q_e]\n", + "bal_closest_Q_e = bal[idx_closest_Q_e]\n", + "\n", + "# find index, q val and bal val of the q closest to Q_i\n", + "idx_closest_Q_i = argmin(abs.(Qs .+ tb.params.Q_i)) # + Q_i since Q_i = -omega_i * Qconv\n", + "q_closest_Q_i = Qs[idx_closest_Q_i]\n", + "bal_closest_Q_i = bal[idx_closest_Q_i]\n", + "\n", + "println(\"Local maxima indices: \", idx_maxima, \" with values: \", maxima, \" and corresponding Qs: \", Qs_maxima, \" closest Q to Q_e: \", q_closest_Q_e, \" closest Q to Q_i: \", q_closest_Q_i)\n", + "# check if 1st q_maxima is same as Q_e or Q_i from p\n", + "if idx_maxima[1] == idx_closest_Q_e || idx_maxima[1] == idx_closest_Q_i\n", + " if length(idx_maxima) < 2\n", + " @warn \"The first local maximum corresponds to a pole from Q_e or Q_i, but there is no second local maximum to select. Try increasing the number of Q samples scanned or adjusting the range.\"\n", + " return Qs, bal, NaN, NaN, NaN, Δs\n", + " end\n", + " println(\"Warning: The first local maximum may correspond to an electron or ion diamagnetic resonance. Selecting the second local maximum instead.\")\n", + " if idx_maxima[2] == idx_closest_Q_e || idx_maxima[2] == idx_closest_Q_i\n", + " @warn \"Both the first and second local maxima correspond to poles from Q_e or Q_i. Unable to select a valid local maximum. Try increasing the number of Q samples scanned or adjusting the range.\"\n", + " return Qs, bal, NaN, NaN, NaN, Δs\n", + " end\n", + " idx_maximum = idx_maxima[2]\n", + " maximum = bal[idx_maximum]\n", + " Qmaximum = Qs[idx_maximum]\n", + "else\n", + " idx_maximum = idx_maxima[1]\n", + " maximum = bal[idx_maximum]\n", + " Qmaximum = Qs[idx_maximum]\n", + "end\n", + "\n", + "println(\"Selected local maximum index: \", idx_maximum, \" with value: \", maximum, \" and corresponding Q: \", Qmaximum)\n", + "\n", + "br_crit = sqrt(maximum / tb.lu * (tb.sval^2 / 2.0))\n", + "\n", + "println(Qmaximum, br_crit, idx_maximum)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6", + "metadata": {}, + "outputs": [], + "source": [ "jxbs = [-imag(1.0 / (d + 1e-2)) for d in Δs]\n", "T_VISC = [2.0 * tb.P * (tb.Q0 - q) for q in Qs] #(q, jxb) in zip(Qs, jxbs)]\n", "#br_t = brcrit\n", @@ -174,13 +313,27 @@ "ylabel!(p2, \"Torque\")\n", "#title!(p2, \"jxb(Q) = -Im[1/(Δ + δ_n_p)]\")\n", "\n", - "p3 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2, xlim=(xmi, xma))\n", + "p3 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2, xlim=(xmi, xma)) #xlim=(-1.3,-.8),ylim=(375,389))#\n", "plot!(p3, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", + "loc_max_ind= [4001, 10050, 10094, 10186, 10195, 10213, 10258, 10272, 10340, 10355, 10365, 10376, 10385, 10387, 10392, 10405, 10412, 10421, 10430, 10443, 10450, 10457, 10470, 10473, 10494, 10498, 10512, 10520, 10537, 10544, 10552, 10557, 10573, 10576, 10578, 10586, 10588, 10596, 10606, 10610, 10632, 10637, 10648, 10655, 10659, 10665, 10670, 10676, 10679, 10691, 10695, 10697, 10705, 10707, 10719, 10730, 10742, 10746, 10751, 10755, 10761, 10765, 10770, 10776, 10778, 10783, 10786, 10788, 10793, 10798, 10810, 10814, 10821, 10824, 10829, 10834, 10837, 10841, 10843, 10847, 10849, 10856, 10858, 10861, 10863, 10868, 10871, 10877, 10881, 10887, 10892, 10895, 10897, 10900, 10904, 10906, 10909, 10911, 10916, 10918, 10923, 10929, 10931, 10933, 10937, 10942, 10945, 10950, 10955, 10959, 10963, 10969, 10971, 10974, 10976, 10981, 10984, 10988, 10991, 10994, 10997, 11001, 11003, 11005, 11012, 11015, 11018, 11021, 11024, 11027, 11029, 11031, 11033, 11036, 11039, 11042, 11044, 11048, 11053, 11056, 11058, 11060, 11062, 11064, 11068, 11078, 11080, 11083, 11085, 11096, 11098, 11100, 11102, 11104, 11106, 11109, 11111, 11116, 11119, 11121, 11128, 11131, 11133, 11139, 11145, 11148, 11150, 11152, 11155, 11157, 11162, 11165, 11169, 11174, 11180, 11183, 11186, 11188, 11205, 11218, 11220, 11222, 11224, 11228, 11233, 11235, 11243, 11249, 11254, 11257, 11259, 11276, 11281, 11294, 11299, 11303, 11306, 11312, 11316, 11319, 11322, 11335, 11341, 11358, 11369, 11376, 11381, 11386, 11391, 11394, 11396, 11399, 11406, 11410, 11417, 11420, 11422, 11428, 11437, 11446, 11448, 11453, 11457, 11469, 11473, 11486, 11497, 11513, 11540, 11542, 11544, 11552, 11554, 11565, 11570, 11573, 11578, 11587, 11594, 11597, 11602, 11614, 11620, 11633, 11654, 11660, 11662, 11669, 11677, 11682, 11687, 11711, 11764, 11804, 11806, 11821, 11848, 11860, 11882, 11901, 11928, 11991, 12108]\n", + "#plot!(p3, Qs[loc_max_ind], bal[loc_max_ind], seriestype=:scatter, label=\"Local Maxima\", color=:red)\n", + "loc_mx2 = [4001, 10963, 10955, 10950, 11005]\n", + "#plot!(p3, Qs[loc_mx2], bal[loc_mx2], seriestype=:scatter, label=\"Local Maxima 2\", color=:green)\n", "ylabel!(p3, \"Torque Balance\")\n", "#title!(p3, \"2P(Q0-Q)/jxb\")\n", "xlabel!(p3, \"Q\")\n", "vline!([Qpeak], label=\"Max Balance\", linestyle=:dash)\n", "\n", + "# find index, q val and bal val of the q closest to Q_e\n", + "println(\"Q_e: \", -tb.params.Q_e)\n", + "idx_closest_Q_e = argmin(abs.(Qs .+ tb.params.Q_e))\n", + "q_closest_Q_e = Qs[idx_closest_Q_e]\n", + "bal_closest_Q_e = bal[idx_closest_Q_e]\n", + "println(\"Closest Q to Q_e: \", q_closest_Q_e, \" with balance value: \", bal_closest_Q_e, \" at index: \", idx_closest_Q_e)\n", + "println(\"B crit: \", brcrit)\n", + "vline!([-tb.params.Q_e], label=\"Q_e\", linestyle=:dashdot, color=:orange)\n", + "vline!([q_closest_Q_e], label=\"Closest Q to Q_e\", linestyle=:dashdot, color=:purple)\n", + "\n", "#plot(p1, p2, p3, layout=(3,1), size=(800, 1000))\n", "plot(p3, layout=(1,1), size=(800, 1000))" ] @@ -188,20 +341,28 @@ { "cell_type": "code", "execution_count": null, - "id": "5", + "id": "7", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8", "metadata": {}, "outputs": [], "source": [ "# compare Q_e to Q of max(bal)\n", "println(\"-Q_e = \", -p.Q_e, \" Q_i = \", p.Q_i, \" Q_peak = \", Qpeak, \" br_crit = \", brcrit)\n", "# check if |Qpeak+Q_e| < 1e-2\n", - "println(\"|Qpeak + Q_e| = \", abs(Qpeak + p.Q_e))" + "println(\"|Qpeak + Q_e| = \", abs(Qpeak + p.Q_e))\n" ] }, { "cell_type": "code", "execution_count": null, - "id": "6", + "id": "9", "metadata": {}, "outputs": [], "source": [ diff --git a/src/Tearing/CriticalResonantField/TorqueBalance.jl b/src/Tearing/CriticalResonantField/TorqueBalance.jl index fbafddc4a..cd74535ea 100644 --- a/src/Tearing/CriticalResonantField/TorqueBalance.jl +++ b/src/Tearing/CriticalResonantField/TorqueBalance.jl @@ -55,7 +55,7 @@ Returns the Q values, torque balance values, positive Q values, positive torque the Q value at the peak, the critical resonant field, the index of the peak Q value, and the Δ values for each Q. """ -function torque_balance_scan(tb; Qmin=-10.0, Qmax=10.0, n=200) +function torque_balance_scan(tb; Qmin=-10.0, Qmax=10.0, n=20000) Qs = range(Qmin, Qmax; length=n) torque_out = [torque_balance_value(tb, q) for q in Qs] bal = [x[1] for x in torque_out] @@ -63,24 +63,78 @@ function torque_balance_scan(tb; Qmin=-10.0, Qmax=10.0, n=200) positive = isfinite.(bal) .& (bal .> 0.0) if !any(positive) - return Qs, bal, [0.0], [0.0], 0.0, 0.0, NaN, Δs + @warn "No positive torque balance found in the specified range. Try increasing the number of Q samples scanned or adjusting the range." + return Qs, bal, NaN, NaN, NaN, Δs end - i = argmax(bal) - Qpeak_ind = i - Qpeak = Qs[i] - maxbal = bal[i] - Qs_positive = Qs[positive] - bal_positive = bal[positive] + # Find the highest point, then remove candidates within ΔQ of it. + idx_maxima = findall(isfinite.(bal) .& (bal .> 0)) + sort!(idx_maxima; by=i -> bal[i], rev=true) + selected = Int[] + min_ΔQ = 0.001 * abs(Qmax - Qmin) - i = argmax(bal_positive) - #Qpeak = Qs_positive[i] + for i in idx_maxima + if all(abs(Qs[i] - Qs[j]) > min_ΔQ for j in selected) + push!(selected, i) + end + length(selected) == 2 && break + end - #maxbal = bal_positive[i] + if isempty(selected) + @warn "No usable positive torque-balance maximum found. Try increasing the number of Q samples scanned or adjusting the range." + return Qs, bal, NaN, NaN, NaN, Δs + end - br_crit = sqrt(maxbal / tb.lu * (tb.sval^2 / 2.0)) - return Qs, bal, Qs_positive, bal_positive, Qpeak, br_crit, Qpeak_ind, Δs -end + idx_maxima = selected + maxima = bal[idx_maxima] + Qs_maxima = Qs[idx_maxima] + + # find index, q val and bal val of the q closest to Q_e + idx_closest_Q_e = argmin(abs.(Qs .+ tb.params.Q_e)) # + Q_e since Q_e = -omega_e * Qconv + q_closest_Q_e = Qs[idx_closest_Q_e] + bal_closest_Q_e = bal[idx_closest_Q_e] + + # find index, q val and bal val of the q closest to Q_i + idx_closest_Q_i = argmin(abs.(Qs .+ tb.params.Q_i)) # + Q_i since Q_i = -omega_i * Qconv + q_closest_Q_i = Qs[idx_closest_Q_i] + bal_closest_Q_i = bal[idx_closest_Q_i] + + println( + "Local maxima indices: ", + idx_maxima, + " with values: ", + maxima, + " and corresponding Qs: ", + Qs_maxima, + " closest Q to Q_e: ", + q_closest_Q_e, + " closest Q to Q_i: ", + q_closest_Q_i + ) -# Need to fix and improve this function. The positive masking is not helpful. -# Need to avoid poles from Q_e and Q_i. + # check if 1st q_maxima is same as Q_e or Q_i from p + if idx_maxima[1] == idx_closest_Q_e || idx_maxima[1] == idx_closest_Q_i + if length(idx_maxima) < 2 + @warn "The first local maximum corresponds to a pole from Q_e or Q_i, but there is no second local maximum to select. Try increasing the number of Q samples scanned or adjusting the range." + return Qs, bal, NaN, NaN, NaN, Δs + end + println("Warning: The first local maximum may correspond to an electron or ion diamagnetic resonance. Selecting the second local maximum instead.") + if idx_maxima[2] == idx_closest_Q_e || idx_maxima[2] == idx_closest_Q_i + @warn "Both the first and second local maxima correspond to poles from Q_e or Q_i. Unable to select a valid local maximum. Try increasing the number of Q samples scanned or adjusting the range." + return Qs, bal, NaN, NaN, NaN, Δs + end + idx_maximum = idx_maxima[2] + maximum = bal[idx_maximum] + Qmaximum = Qs[idx_maximum] + else + idx_maximum = idx_maxima[1] + maximum = bal[idx_maximum] + Qmaximum = Qs[idx_maximum] + end + + println("Selected local maximum index: ", idx_maximum, " with value: ", maximum, " and corresponding Q: ", Qmaximum) + + br_crit = sqrt(maximum / tb.lu * (tb.sval^2 / 2.0)) + + return Qs, bal, Qmaximum, br_crit, idx_maximum, Δs +end diff --git a/src/Tearing/Runner/Control.jl b/src/Tearing/Runner/Control.jl index 88e8fe091..bbf297975 100644 --- a/src/Tearing/Runner/Control.jl +++ b/src/Tearing/Runner/Control.jl @@ -7,6 +7,41 @@ # # `CriticalResonantFieldControl` holds the user-facing knobs that drive the critical resonant field # analysis. Populated either directly via the `@kwdef` constructor or by parsing the `[CriticalResonantField]` section of a `gpec.toml`. +""" + CriticalResonantFieldControl + +Configuration for the critical resonant field analysis. All fields are +user-facing: read from the `[CriticalResonantField]` TOML section of a `gpec.toml` via +`critical_resonant_field_control_from_toml`, or built directly via the `@kwdef` keyword +constructor. +""" +@kwdef struct CriticalResonantFieldControl + enabled::Bool = false + Qmin::Float64 = -10.0 + Qmax::Float64 = 10.0 + n::Int = 200 + angular_momentum_diffusivity::Union{Float64,Vector{Float64}} = 1.0 + store_scan::Bool = false +end + +function critical_resonant_field_control_from_toml(section::AbstractDict) + flat = Dict{String,Any}() + for (k, v) in section + flat[k] = v + end + + kwargs = Dict{Symbol,Any}() + for (k, v) in flat + sym = Symbol(k) + if sym in (:inner_model,) + kwargs[sym] = v isa Symbol ? v : Symbol(String(v)) + else + kwargs[sym] = v + end + end + + return CriticalResonantFieldControl(; kwargs...) +end """ SLAYERControl @@ -158,6 +193,9 @@ there is one consistent interface for resistive and kinetic profiles. profile_group::String = "/" store_scan::Bool = false + + # Critical resonant field analysis. Enabled via `[SLAYER.CriticalResonantField]` TOML section. + critical_resonant_field::CriticalResonantFieldControl = CriticalResonantFieldControl() end const _VALID_INNER_MODELS = (:slayer_fitzpatrick, :ggj_shooting, :ggj_galerkin) @@ -227,6 +265,10 @@ function slayer_control_from_toml(section::AbstractDict) haskey(v, "pole_threshold") && (flat["pole_threshold"] = v["pole_threshold"]) haskey(v, "filter_above_poles") && (flat["filter_above_poles"] = v["filter_above_poles"]) haskey(v, "filter_outside_re") && (flat["filter_outside_re"] = v["filter_outside_re"]) + elseif k == "CriticalResonantField" && v isa AbstractDict + flat["critical_resonant_field"] = + critical_resonant_field_control_from_toml(v) + else flat[k] = v end @@ -271,41 +313,3 @@ function slayer_control_from_toml(section::AbstractDict) end return validate(SLAYERControl(; kwargs...)) end - -""" - CriticalResonantFieldControl - -Configuration for the critical resonant field analysis. All fields are -user-facing: read from the `[CriticalResonantField]` TOML section of a `gpec.toml` via -`critical_resonant_field_control_from_toml`, or built directly via the `@kwdef` keyword -constructor. -""" -@kwdef struct CriticalResonantFieldControl - enabled::Bool = false - inner_model::Symbol = :slayer_fitzpatrick - Qmin::Float64 = -10.0 - Qmax::Float64 = 10.0 - n::Int = 200 - profile_file::String = "" - profile_group::String = "/" - store_scan::Bool = false -end - -function critical_resonant_field_control_from_toml(section::AbstractDict) - flat = Dict{String,Any}() - for (k, v) in section - flat[k] = v - end - - kwargs = Dict{Symbol,Any}() - for (k, v) in flat - sym = Symbol(k) - if sym in (:inner_model,) - kwargs[sym] = v isa Symbol ? v : Symbol(String(v)) - else - kwargs[sym] = v - end - end - - return CriticalResonantFieldControl(; kwargs...) -end diff --git a/src/Tearing/Runner/HDF5Output.jl b/src/Tearing/Runner/HDF5Output.jl index 006f2d079..2ae545211 100644 --- a/src/Tearing/Runner/HDF5Output.jl +++ b/src/Tearing/Runner/HDF5Output.jl @@ -38,6 +38,10 @@ function write_slayer_hdf5!(parent::Union{HDF5.File,HDF5.Group}, # disjoint field sets, so readers must not have to infer it from the schema. attrs(g)["layer_model"] = result.enabled ? _layer_model_token(eltype(result.params)) : "none" + if result.critical_resonant_field.enabled + write_critical_resonant_field_hdf5!(g, result.critical_resonant_field) + end + if !result.enabled # nothing else to write _annotate_tearing!(g) return g @@ -60,10 +64,7 @@ end function write_critical_resonant_field_hdf5!(parent::Union{HDF5.File,HDF5.Group}, result::CriticalResonantFieldResult) - if !haskey(parent, "Tearing") - create_group(parent, "Tearing") - end - g = create_group(parent["Tearing"], "CriticalResonantField") + g = create_group(parent, "CriticalResonantField") g["surface_index"] = result.surface_index g["Qpeak"] = result.Qpeak @@ -78,8 +79,6 @@ function write_critical_resonant_field_hdf5!(parent::Union{HDF5.File,HDF5.Group} sg["Q"] = d.Q sg["balance"] = d.balance sg["delta"] = d.delta - sg["Q_positive"] = d.Q_positive - sg["balance_positive"] = d.balance_positive sg["Qpeak"] = d.Qpeak sg["br_crit"] = d.br_crit diff --git a/src/Tearing/Runner/Result.jl b/src/Tearing/Runner/Result.jl index 9132e8421..df68bb868 100644 --- a/src/Tearing/Runner/Result.jl +++ b/src/Tearing/Runner/Result.jl @@ -8,6 +8,37 @@ # per-surface critical resoant field. If `control.store_scan` is true, the full Q scan data, # viscous torque, and electromagnetic torque are also stored for plotting. +""" + CriticalResonantFieldResult + +Output of `run_critical_resonant_field`. Carries both summary critical resonant field values and if `control.store_scan` is true, the full Q scan data, viscous torque, and electromagnetic torque for plotting. +""" + +struct CriticalResonantFieldResult + enabled::Bool + params::AbstractVector{<:InnerLayerParameters} + surface_index::Vector{Int} + Qpeak::Vector{Float64} + br_crit::Vector{Float64} + Q0::Vector{Float64} + P::Vector{Float64} + scan_data::Vector{NamedTuple} +end + +function empty_critical_resonant_field_result() + return CriticalResonantFieldResult( + false, + InnerLayerParameters[], + Int[], + Float64[], + Float64[], + Float64[], + Float64[], + NamedTuple[] + ) +end + + """ SLAYERResult @@ -55,46 +86,18 @@ struct SLAYERResult coupled_extraction::Union{Nothing,GrowthRateResult} layer_widths::Vector{LayerWidths} scan_data::Vector{Union{ScanResult,AMRResult}} + critical_resonant_field::CriticalResonantFieldResult end # Empty result (enabled=false path) function empty_slayer_result(control::SLAYERControl) return SLAYERResult(false, control, - SLAYERParameters[], - Float64[], Float64[], - zeros(ComplexF64, 0, 0), - ComplexF64[], Float64[], Float64[], - GrowthRateResult[], nothing, - LayerWidths[], - Union{ScanResult,AMRResult}[]) -end - -""" - CriticalResonantFieldResult - -Output of `run_critical_resonant_field`. Carries both summary critical resonant field values and if `control.store_scan` is true, the full Q scan data, viscous torque, and electromagnetic torque for plotting. -""" - -struct CriticalResonantFieldResult - enabled::Bool - params::AbstractVector{<:InnerLayerParameters} - surface_index::Vector{Int} - Qpeak::Vector{Float64} - br_crit::Vector{Float64} - Q0::Vector{Float64} - P::Vector{Float64} - scan_data::Vector{NamedTuple} -end - -function empty_critical_resonant_field_result() - return CriticalResonantFieldResult( - false, - InnerLayerParameters[], - Int[], - Float64[], - Float64[], - Float64[], - Float64[], - NamedTuple[] - ) + SLAYERParameters[], + Float64[], Float64[], + zeros(ComplexF64, 0, 0), + ComplexF64[], Float64[], Float64[], + GrowthRateResult[], nothing, + LayerWidths[], + Union{ScanResult,AMRResult}[], + empty_critical_resonant_field_result()) end diff --git a/src/Tearing/Runner/Runner.jl b/src/Tearing/Runner/Runner.jl index 6f11208a7..2d45b3d54 100644 --- a/src/Tearing/Runner/Runner.jl +++ b/src/Tearing/Runner/Runner.jl @@ -27,6 +27,7 @@ using LinearAlgebra using Statistics: mean, median using HDF5 + using FastInterpolations: cubic_interp using ..Utilities using ..Utilities: KineticProfiles diff --git a/src/Tearing/Runner/run_slayer.jl b/src/Tearing/Runner/run_slayer.jl index 3d51d4a11..9f1a686d1 100644 --- a/src/Tearing/Runner/run_slayer.jl +++ b/src/Tearing/Runner/run_slayer.jl @@ -314,7 +314,7 @@ function run_slayer_from_inputs(params::AbstractVector{<:InnerLayerParameters}, return SLAYERResult(true, control, params, rational_psi, rational_q, dp, Q_root, omega_Hz, gamma_Hz, per_surface_extraction, coupled_extraction, - layer_widths, scan_data_list) + layer_widths, scan_data_list, empty_critical_resonant_field_result()) end # --------------------------------------------------------------------- @@ -346,6 +346,115 @@ function ggj_inner_deltas(params::AbstractVector{GGJParameters}, Q::Number; end return out end +# --------------------------------------------------------------------- +# Critical Resonant Field (Torque-Balance) Workflow +# --------------------------------------------------------------------- +""" + Critical Resonant Field (Torque-Balance) Workflow + + The critical resonant field is the minimum resonant magnetic perturbation + amplitude that can drive a tearing mode unstable. + + Returns a `CriticalResonantFieldResult` containing the critical resonant field + and the corresponding critical resoannt field values for each rational surface. +""" + +function run_critical_resonant_field(equil, intr, ctrl; dir_path="./", slayer_result=nothing, profiles=nothing) + ctrl.enabled || return empty_critical_resonant_field_result() + + profiles === nothing && + throw(ArgumentError( + "CriticalResonantField requires kinetic profiles." + )) + + params = if slayer_result !== nothing && slayer_result.enabled && !isempty(slayer_result.params) + slayer_result.params + else + throw(ArgumentError("CriticalResonantField requires SLAYERParameters; run SLAYER first or provide compatible params.")) + end + + all(p -> p isa SLAYERParameters, params) || + throw(ArgumentError("CriticalResonantField requires SLAYERParameters; run SLAYER first or provide compatible params.")) + + surface_index = Int[] + Qpeak_vec = Float64[] + br_vec = Float64[] + Q0_vec = Float64[] + P_vec = Float64[] + scan_data = NamedTuple[] + # check if angular_momentum_diffusivity is list or value + + if isa(ctrl.angular_momentum_diffusivity, AbstractArray) + chi_vec = ctrl.angular_momentum_diffusivity + else + chi_vec = fill(ctrl.angular_momentum_diffusivity, length(params)) + end + + for (isurf, p) in enumerate(params) + psi_here = intr[isurf].psifac + omega_here = profiles(psi_here).omega + Q0_here = p.tauk * omega_here + eta_here = p.eta # resistivity at the rational surface + chi_here = chi_vec[isurf] # angular momentum diffusivity at the rational surface + + # Note, P = τ_R / τ_V (Cole PoP 2006), τ_R = μ₀ r_s² / η, τ_V = ρ r_s² / μ + # Therefore, P = τ_R / τ_V = μ₀ μ / (η ρ), and with χ_φ = μ / ρ, P = μ₀ χ_φ / η + + P_here = (4π * 1e-7) .* abs.(chi_here) ./ eta_here + + if P_here < 1 + @warn("CriticalResonantField: P < 1 at surface $isurf (P = $P_here). The model is invalid for P < 1.") + end + + tb = TorqueBalance( + SLAYERModel{:fitzpatrick}(), + p, + Q0_here, + P_here, + p.lu, + p.sval_r + ) + + Qs, bal, Qpeak, br_crit, Qpeak_ind, Δs = + torque_balance_scan(tb; Qmin=ctrl.Qmin, Qmax=ctrl.Qmax, n=ctrl.n) + + push!(surface_index, isurf) + push!(Qpeak_vec, Qpeak) + push!(br_vec, br_crit) + push!(Q0_vec, Q0_here) + push!(P_vec, P_here) + + scan_entry = ( + surface=isurf, + Q=collect(Qs), + balance=collect(bal), + delta=collect(Δs), + Qpeak=Qpeak, + br_crit=br_crit, + Q0=Q0_here, + P=P_here, + lu=p.lu, + sval=p.sval_r, + m=p.m, + n=p.n, + params=p + ) + push!(scan_data, scan_entry) + + end + + return CriticalResonantFieldResult( + true, + params, + surface_index, + Qpeak_vec, + br_vec, + Q0_vec, + P_vec, + scan_data + ) +end + # --------------------------------------------------------------------- # Full pipeline: equilibrium + ForceFreeStates → parameters → analysis @@ -453,96 +562,30 @@ function run_slayer(equil, surfaces::AbstractVector, delta_prime_matrix::Abstrac rational_psi = Float64[surfaces[p.ising].psifac for p in params] rational_q = Float64[surfaces[p.ising].q for p in params] - return run_slayer_from_inputs(params, dp, control; rational_psi=rational_psi, rational_q=rational_q) -end - -# --------------------------------------------------------------------- -# Critical Resonant Field (Torque-Balance) Workflow -# --------------------------------------------------------------------- -""" - Critical Resonant Field (Torque-Balance) Workflow - - The critical resonant field is the minimum resonant magnetic perturbation - amplitude that can drive a tearing mode unstable. - - Returns a `CriticalResonantFieldResult` containing the critical resonant field - and the corresponding critical resoannt field values for each rational surface. -""" - -function run_critical_resonant_field(equil, intr, ctrl; dir_path="./", slayer_result=nothing) - ctrl.enabled || return empty_critical_resonant_field_result() - - profiles = load_kinetic_profiles(joinpath(dir_path, ctrl.profile_file)) - - params = if slayer_result !== nothing && slayer_result.enabled && !isempty(slayer_result.params) - slayer_result.params - else - build_slayer_inputs(equil, intr.sing, profiles) - end - - all(p -> p isa SLAYERParameters, params) || - throw(ArgumentError("CriticalResonantField requires SLAYERParameters; run SLAYER first or provide compatible params.")) - - surface_index = Int[] - Qpeak_vec = Float64[] - br_vec = Float64[] - Q0_vec = Float64[] - P_vec = Float64[] - scan_data = NamedTuple[] - - for (isurf, p) in enumerate(params) - psi_here = intr.sing[isurf].psifac - omega_here = profiles(psi_here).omega - Q0_here = p.tauk * omega_here - P_here = 1.0 - - tb = TorqueBalance( - SLAYERModel{:fitzpatrick}(), - p, - Q0_here, - P_here, - p.lu, - p.sval_r + # include critical resonant filed workflow here + if control.critical_resonant_field.enabled + slayer_result = run_slayer_from_inputs(params, dp, control; rational_psi=rational_psi, rational_q=rational_q) + crf_result = run_critical_resonant_field(equil, surfaces, control.critical_resonant_field; + dir_path=dir_path, slayer_result=slayer_result, profiles=profiles) + combined_result = SLAYERResult( + slayer_result.enabled, + slayer_result.control, + slayer_result.params, + slayer_result.rational_psi, + slayer_result.rational_q, + slayer_result.dp_matrix, + slayer_result.Q_root, + slayer_result.omega_Hz, + slayer_result.gamma_Hz, + slayer_result.per_surface_extraction, + slayer_result.coupled_extraction, + slayer_result.layer_widths, + slayer_result.scan_data, + crf_result ) - - Qs, bal, Qs_positive, bal_positive, Qpeak, br_crit, Qpeak_ind, Δs = - torque_balance_scan(tb; Qmin=ctrl.Qmin, Qmax=ctrl.Qmax, n=ctrl.n) - - push!(surface_index, isurf) - push!(Qpeak_vec, Qpeak) - push!(br_vec, br_crit) - push!(Q0_vec, Q0_here) - push!(P_vec, P_here) - - scan_entry = ( - surface=isurf, - Q=collect(Qs), - balance=collect(bal), - delta=collect(Δs), - Q_positive=collect(Qs_positive), - balance_positive=collect(bal_positive), - Qpeak=Qpeak, - br_crit=br_crit, - Q0=Q0_here, - P=P_here, - lu=p.lu, - sval=p.sval_r, - m=p.m, - n=p.n, - params=p - ) - push!(scan_data, scan_entry) - + @info("SLAYER: critical resonant field workflow completed; " * + "critical br values for each rational surface are available in the result.") + return combined_result end - - return CriticalResonantFieldResult( - true, - params, - surface_index, - Qpeak_vec, - br_vec, - Q0_vec, - P_vec, - scan_data - ) + return run_slayer_from_inputs(params, dp, control; rational_psi=rational_psi, rational_q=rational_q) end From fbacf333c2312537a76b336d4a0cdff79c71c059 Mon Sep 17 00:00:00 2001 From: ebursch <76970916+ebursch@users.noreply.github.com> Date: Thu, 20 Aug 2026 14:07:27 -0400 Subject: [PATCH 7/9] Full working bcrit intial implementation --- .gitignore | 2 + .../gpec.toml | 20 +- .../slayer_ex.ipynb | 394 ++++++++++ .../DIIID-like_SLAYER_example/slayer_ex.ipynb | 266 ------- .../CRF Dev/P_eta_calc.ipynb | 279 ------- .../CriticalResonantField/CRF Dev/b_crit.jls | Bin 74 -> 0 bytes .../CRF Dev/bcrit_dev.ipynb | 724 ------------------ .../CRF Dev/bcrit_dev_ggj.ipynb | 298 ------- .../CRF Dev/bcrit_numerics.ipynb | 122 --- .../CriticalResonantField/CRF Dev/gslayer.txt | 466 ----------- .../CRF Dev/pole_testing.ipynb | 395 ---------- .../CRF Dev/sample_number.jls | Bin 68 -> 0 bytes .../CriticalResonantField.jl | 1 + .../CriticalResonantField/TorqueBalance.jl | 35 +- src/Tearing/Runner/Control.jl | 3 +- src/Tearing/Runner/run_slayer.jl | 115 ++- 16 files changed, 511 insertions(+), 2609 deletions(-) rename examples/{DIIID-like_SLAYER_example => DIIID-like_SLAYER_and_bcrit_example}/gpec.toml (84%) create mode 100644 examples/DIIID-like_SLAYER_and_bcrit_example/slayer_ex.ipynb delete mode 100644 examples/DIIID-like_SLAYER_example/slayer_ex.ipynb delete mode 100644 src/Tearing/CriticalResonantField/CRF Dev/P_eta_calc.ipynb delete mode 100644 src/Tearing/CriticalResonantField/CRF Dev/b_crit.jls delete mode 100644 src/Tearing/CriticalResonantField/CRF Dev/bcrit_dev.ipynb delete mode 100644 src/Tearing/CriticalResonantField/CRF Dev/bcrit_dev_ggj.ipynb delete mode 100644 src/Tearing/CriticalResonantField/CRF Dev/bcrit_numerics.ipynb delete mode 100644 src/Tearing/CriticalResonantField/CRF Dev/gslayer.txt delete mode 100644 src/Tearing/CriticalResonantField/CRF Dev/pole_testing.ipynb delete mode 100644 src/Tearing/CriticalResonantField/CRF Dev/sample_number.jls diff --git a/.gitignore b/.gitignore index fcb3cc96c..8f463f94f 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,5 @@ scratch/ # Local profiling scratch (one-off study scripts, not part of the package) profiling/ +examples/b_crit_standalone_example/ +src/Tearing/CriticalResonantField/CRF Dev/ diff --git a/examples/DIIID-like_SLAYER_example/gpec.toml b/examples/DIIID-like_SLAYER_and_bcrit_example/gpec.toml similarity index 84% rename from examples/DIIID-like_SLAYER_example/gpec.toml rename to examples/DIIID-like_SLAYER_and_bcrit_example/gpec.toml index 618372d02..b00fad0cc 100644 --- a/examples/DIIID-like_SLAYER_example/gpec.toml +++ b/examples/DIIID-like_SLAYER_and_bcrit_example/gpec.toml @@ -1,7 +1,7 @@ -# DIII-D-like SLAYER tearing-mode growth-rate example. +# DIII-D-like SLAYER tearing-mode growth-rate example with Critical Resonant Field calculations. # Reuses the equilibrium and H-mode kinetic profiles of the sibling # DIIID-like_ideal_example (geqdsk referenced by relative path; not -# duplicated). Runs equilibrium + ForceFreeStates + SLAYER and skips +# duplicated). Runs equilibrium + ForceFreeStates + SLAYER + CriticalResonantField and skips # PerturbedEquilibrium (ForceFreeStates.force_termination = true). [Equilibrium] @@ -87,11 +87,11 @@ Q_im_range = [-0.5, 3.0] # Scan box in the normalized Q plane, Im(Q) axis nre = 41 # Grid resolution along the Re(Q) axis nim = 31 # Grid resolution along the Im(Q) axis -[SLAYER.CriticalResonantField] -# CriticalResonantField used to find the critical resonant field sufficent for tearing onset at each rational surface. -enabled = true # Run CriticalResonantField analysis -Qmin = -10 # Minimum rotation scanned -Qmax = 10 # Maximum rotation scanned -n = 200 # Number of rotation points scanned -angular_momentum_diffusivity = [1.0,1.0,1.0,1.0,1.0,1.0] # Toroidal momentum diffusivity (if nothing, falls back on chi_perp ~ chi_e, electron thermal diffusivity) -store_scan = true # Per surface torque and inner layer quantities +[SLAYER.CriticalResonantField] # CriticalResonantField used to find the critical resonant field sufficent for tearing onset at each rational surface. +enabled = true # Run CriticalResonantField analysis +Qmin = -10 # Minimum normalized rotation scanned +Qmax = 10 # Maximum normalized rotation scanned +n = 2000 # Number of rotation points scanned +viscous_input_type = "angular_momentum_diffusivity" # Either "angular_momentum_diffusivity" or "magnetic_prandtl_number" +viscous_input = 1 # Either Prandlt number or angular momentum diffusivity (based on viscous_input_type). Takes in either an array across q surfaces, a single value for all, or false, which falls back on chi_perp ~ chi_e, electron thermal diffusivity. +store_scan = true # Per surface torque and inner layer quantities diff --git a/examples/DIIID-like_SLAYER_and_bcrit_example/slayer_ex.ipynb b/examples/DIIID-like_SLAYER_and_bcrit_example/slayer_ex.ipynb new file mode 100644 index 000000000..ed88780dd --- /dev/null +++ b/examples/DIIID-like_SLAYER_and_bcrit_example/slayer_ex.ipynb @@ -0,0 +1,394 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "0", + "metadata": {}, + "outputs": [], + "source": [ + "using Pkg\n", + "Pkg.build(\"GeneralizedPerturbedEquilibrium\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1", + "metadata": {}, + "outputs": [], + "source": [ + "using Pkg\n", + "Pkg.activate(\"/Users/bursche/Documents/GitHub/JPEC_BCRIT\")\n", + "Base.active_project()\n", + "\n", + "using GeneralizedPerturbedEquilibrium\n", + "using GeneralizedPerturbedEquilibrium: Analysis\n", + "using Printf\n", + "\n", + "using Plots\n", + "default(\n", + " fontfamily=\"Georgia\",\n", + " margin=12Plots.mm,\n", + " size=(800, 500),\n", + " dpi=150\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2", + "metadata": {}, + "outputs": [], + "source": [ + "h5path = \"/Users/bursche/Documents/GitHub/JPEC_BCRIT/examples/DIIID-like_SLAYER_and_bcrit_example/gpec.h5\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3", + "metadata": {}, + "outputs": [], + "source": [ + "using HDF5\n", + "\n", + "h5open(h5path, \"r\") do file\n", + " println(\"Top-level keys:\")\n", + " println(collect(keys(file)))\n", + "\n", + " if haskey(file, \"Tearing\")\n", + " println(\"\\nKeys in Tearing:\")\n", + " println(collect(keys(file[\"Tearing\"])))\n", + "\n", + " if haskey(file[\"Tearing\"], \"CriticalResonantField\")\n", + " println(\"\\nKeys in Tearing/CriticalResonantField:\")\n", + " println(collect(keys(file[\"Tearing\"][\"CriticalResonantField\"])))\n", + " end\n", + " else\n", + " println(\"No Tearing group found.\")\n", + " end\n", + "end" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4", + "metadata": {}, + "outputs": [], + "source": [ + "# Print the contents of the Tearing/CriticalResonantField group\n", + "h5open(h5path, \"r\") do file\n", + " if haskey(file, \"Tearing\") && haskey(file[\"Tearing\"], \"CriticalResonantField\")\n", + " println(\"\\nContents of Tearing/CriticalResonantField:\")\n", + " # Iterate over the keys in the Tearing/CriticalResonantField group and print their names and types\n", + " for key in keys(file[\"Tearing\"][\"CriticalResonantField\"])\n", + " dataset = file[\"Tearing\"][\"CriticalResonantField\"][key]\n", + " println(\"Key: $key, Type: $(typeof(dataset))\")\n", + " # print data \n", + " if isa(dataset, HDF5.Dataset)\n", + " data = read(dataset)\n", + " println(\"Data: $data\")\n", + " end\n", + " end\n", + " else\n", + " println(\"No Tearing/CriticalResonantField group found.\")\n", + " end\n", + " # Print bcrit data as .2e (in one line)\n", + " println(\"\\nBcrit data: $(join([@sprintf(\"%.2e\", x) for x in read(file[\"Tearing\"][\"CriticalResonantField\"][\"br_crit\"])], \" \"))\")\n", + "end\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5", + "metadata": {}, + "outputs": [], + "source": [ + "println(keys(h5open(h5path, \"r\")[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_1\"]))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7", + "metadata": {}, + "outputs": [], + "source": [ + "function bcrit_diag_plots(Δs, Qs, bal, name)\n", + "\n", + " p1 = plot(Qs, imag.(Δs), label=\"Im(Δ)\", lw=2)\n", + " #plot!(p1, Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", + " xlabel!(p1, \"Q\")\n", + " ylabel!(p1, \"Δ\")\n", + " title!(p1, \"Inner-layer Δ(Q) - $name\")\n", + "\n", + " p2 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2)\n", + " plot!(p2, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", + " xlabel!(p2, \"Q\")\n", + " ylabel!(p2, \"balance\")\n", + " title!(p2, \"2P(Q0-Q)/jxb - $name\")\n", + "\n", + " plot(p1, p2, layout=(2,1), size=(500, 700))\n", + "\n", + "\n", + "end\n", + "\n", + "function plot_all_vs_rational_q(h5path)\n", + " h5open(h5path, \"r\") do file\n", + " tearing = file[\"Tearing\"]\n", + " crf = tearing[\"CriticalResonantField\"]\n", + " scan = crf[\"Scan\"]\n", + "\n", + " rational_q = read(tearing[\"PerSurface\"][\"rational_q\"])\n", + " bcrit = read(crf[\"br_crit\"])\n", + " bal = [read(scan[\"surface_$(i)\"][\"balance\"]) for i in eachindex(rational_q)]\n", + " P = [read(scan[\"surface_$(i)\"][\"P\"]) for i in eachindex(rational_q)]\n", + " lu = [read(scan[\"surface_$(i)\"][\"lu\"]) for i in eachindex(rational_q)]\n", + " sval = [read(scan[\"surface_$(i)\"][\"sval\"]) for i in eachindex(rational_q)]\n", + " Q0 = [read(scan[\"surface_$(i)\"][\"Q0\"]) for i in eachindex(rational_q)]\n", + " max_balance = maximum.(bal)\n", + "\n", + " fig = plot(layout=(3, 2), size=(1000, 1200))\n", + " plot!(fig[1], rational_q, bcrit; marker=:circle, lw=2, xlabel=\"Rational Surface (q)\", ylabel=\"Critical Resonant Field (T)\", legend=false)\n", + " plot!(fig[2], rational_q, max_balance; marker=:circle, lw=2, xlabel=\"Rational Surface (q)\", ylabel=\"Maximum (Torque Balance)\", legend=false)\n", + " plot!(fig[3], rational_q, P; marker=:circle, lw=2, xlabel=\"Rational Surface (q)\", ylabel=\"P\", legend=false)\n", + " plot!(fig[4], rational_q, lu; marker=:circle, lw=2, xlabel=\"Rational Surface (q)\", ylabel=\"Lundquist Number\", legend=false)\n", + " plot!(fig[5], rational_q, sval; marker=:circle, lw=2, xlabel=\"Rational Surface (q)\", ylabel=\"Magnetic Shear\", legend=false)\n", + " plot!(fig[6], rational_q, Q0; marker=:circle, lw=2, xlabel=\"Rational Surface (q)\", ylabel=\"Q0\", legend=false)\n", + "\n", + " display(fig)\n", + " #return fig\n", + " end\n", + "end\n", + "\n", + "plot_all_vs_rational_q(h5path)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8", + "metadata": {}, + "outputs": [], + "source": [ + "using GeneralizedPerturbedEquilibrium\n", + "using GeneralizedPerturbedEquilibrium: Analysis\n", + "using GeneralizedPerturbedEquilibrium.InnerLayer: InnerLayerModel, solve_inner, GGJModel, GGJParameters,\n", + " SLAYERModel, SLAYERParameters, slayer_parameters\n", + "using GeneralizedPerturbedEquilibrium.Tearing.CriticalResonantField: TorqueBalance, torque_balance_value, torque_balance_scan\n", + "\n", + "surface_num = 5\n", + "h5open(h5path, \"r\") do file\n", + " sval_r = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"sval\"])\n", + " Q0 = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"Q0\"])\n", + " m = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"m\"])\n", + " n = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"n\"])\n", + " qval = m/n\n", + " Q_e = read(file[\"Tearing\"][\"PerSurface\"][\"Q_e\"])[surface_num]\n", + " Q_i = read(file[\"Tearing\"][\"PerSurface\"][\"Q_i\"])[surface_num]\n", + " lu = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"lu\"])\n", + " rs = read(file[\"Tearing\"][\"PerSurface\"][\"rs\"])[surface_num]\n", + " P = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"P\"])\n", + "\n", + " p = slayer_parameters( # Call slayer_parameters function to instantiate slab parameters\n", + " n_e=1e19, t_e=1e3, t_i=1e3,\n", + " omega=0.0, omega_e=40, omega_i=-20,\n", + " qval=qval, sval_r=sval_r, bt=2.0, rs=rs, R0=3.0, mu_i=2.0, zeff=1.0,\n", + " chi_perp=1.0, chi_tor=1.0, m=2, n=1\n", + " )\n", + " p = SLAYERParameters( # Modify the created SLAYERParameters struct to modify electron and ion diamagnetic resonance frequencies\n", + " ising=p.ising,\n", + " m=p.m, n=p.n,\n", + " tau=p.tau, lu=p.lu, c_beta=p.c_beta, D_norm=p.D_norm,\n", + " P_perp=p.P_perp, P_tor=p.P_tor,\n", + " Q_e=Q_e, Q_i=Q_i, iota_e=p.iota_e,\n", + " tauk=p.tauk, tau_r=p.tau_r, delta_n=p.delta_n,\n", + " rs=p.rs, R0=p.R0, bt=p.bt, sval_r=p.sval_r,\n", + " dr_val=p.dr_val, dgeo_val=p.dgeo_val,\n", + " eta=p.eta, d_beta=p.d_beta,\n", + " dc_tmp=p.dc_tmp, dc_type=p.dc_type\n", + " )\n", + "\n", + " tb = TorqueBalance( # Generate a TorqueBalance struct using the default (Fitzpatrick) SLAYERModel and the modified SLAYERParameters\n", + " SLAYERModel(;),\n", + " p, # Slayer Parameters struct\n", + " Q0, # Normalized rotation Q\n", + " P, # Magnetic Prandtl number\n", + " p.lu, # Lundquist Number\n", + " p.sval_r # r-based magnetic shear\n", + " )\n", + " Qmin = -.2\n", + " Qmax = .2\n", + " Qs, bal, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb,Qmin=Qmin, Qmax=Qmax, n=1000) # Run actual torque balance scan, finds inner-layer delta across Q vals\n", + "\n", + "\n", + " jxbs = [-imag(1.0 / (d + 1e-2)) for d in Δs]\n", + " T_VISC = [2.0 * tb.P * (tb.Q0 - q) for q in Qs] #(q, jxb) in zip(Qs, jxbs)]\n", + " T_EM = -imag(1.0 ./ (Δs .+ 1e-2)) *brcrit^2*tb.lu/(tb.sval^2/2)\n", + " i = Qpeak_ind\n", + " println(T_VISC[i]/(tb.lu * tb.sval^2/2 * (brcrit)^2 * jxbs[i]))\n", + " println(T_VISC[i] / (tb.lu * tb.sval^2/2 * (brcrit * p.bt)^2 * jxbs[i]))\n", + " println(T_VISC[i] / ( (brcrit / p.bt)^2 * jxbs[i]))\n", + "\n", + " #T_EM ∝ S ξ̂ (br/Bφ)² Im[-Δ̂(Q)⁻¹]\n", + " #T_visc ∝ 2 P (Q0 − Q)\n", + "\n", + "\n", + " xmi = Qmin\n", + " xma = Qmax\n", + "\n", + " \"\"\"\n", + " p1 = plot(Qs, imag.(Δs), label=\"Im(Δ)\", lw=2, xlim=(xmi, xma))\n", + " #plot!(p1, Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", + " xlabel!(p1, \"Q\")\n", + " ylabel!(p1, \"Δ\")\n", + " #title!(p1, \"Inner-layer Δ(Q)\")\n", + " \"\"\"\n", + "\n", + " p1 = plot( Qs, T_VISC, label=\"T_V\", lw=2, xlim=(xmi, xma))#,ylim=(-1000,1000))\n", + " plot!(p1, Qs, T_EM, label=\"T_EM\", lw=2)\n", + " vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + " xlabel!(p1, \"Q\")\n", + " ylabel!(p1, \"Torque\")\n", + "\n", + " #p2 = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", + " p2 = plot( Qs, T_VISC, label=\"T_V\", lw=2, xlim=(xmi, xma))#,ylim=(0,500))\n", + " plot!(p2, Qs, T_EM, label=\"T_EM\", lw=2)\n", + " vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", + " xlabel!(p2, \"Q\")\n", + " ylabel!(p2, \"Torque\")\n", + "\n", + " p3 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2, xlim=(xmi, xma),ylim=(-1e-2,1e-2))\n", + " plot!(p3, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", + " ylabel!(p3, \"Torque Balance\")\n", + " xlabel!(p3, \"Q\")\n", + " vline!([Qpeak], label=\"Max Balance\", linestyle=:dash)\n", + "\n", + " # find index, q val and bal val of the q closest to Q_e\n", + " println(\"Q_e: \", -tb.params.Q_e)\n", + " idx_closest_Q_e = argmin(abs.(Qs .+ tb.params.Q_e))\n", + " q_closest_Q_e = Qs[idx_closest_Q_e]\n", + " bal_closest_Q_e = bal[idx_closest_Q_e]\n", + " println(\"Closest Q to Q_e: \", q_closest_Q_e, \" with balance value: \", bal_closest_Q_e, \" at index: \", idx_closest_Q_e)\n", + " println(\"B crit: \", brcrit)\n", + " vline!([-tb.params.Q_e], label=\"Q_e\", linestyle=:dashdot, color=:orange)\n", + " vline!([q_closest_Q_e], label=\"Closest Q to Q_e\", linestyle=:dashdot, color=:purple)\n", + "\n", + " #plot(p1, p2, p3, layout=(3,1), size=(800, 1000))\n", + " plot(p3, layout=(1,1))#, size=(800, 1000))\n", + "\n", + "end" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9", + "metadata": {}, + "outputs": [], + "source": [ + "# plot jxb vs Qs for surface 1\n", + "# jxbs = [-imag(1.0 / (d + 1e-2)) for d in Δs]\n", + "surface_num = 5\n", + "h5open(h5path, \"r\") do file\n", + " Δs = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"delta\"])\n", + " Qs = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"Q\"])\n", + " bal = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"balance\"])\n", + " jxbs = [-imag(1.0 / (d + 1e-2)) for d in Δs]\n", + " aplot = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", + " xlabel!(\"Q\")\n", + " ylabel!(\"jxb\")\n", + " title!(\"jxb vs Q for surface $(surface_num)\")\n", + " println(\"max of balance: \", maximum(bal))\n", + " println(\"max of jxb: \", maximum(jxbs))\n", + " println(\"bcrit: \", read(file[\"Tearing\"][\"CriticalResonantField\"][\"br_crit\"]))\n", + " println(\"Qpeak: \", read(file[\"Tearing\"][\"CriticalResonantField\"][\"Qpeak\"]))\n", + " println(\"Q_e: \", read(file[\"Tearing\"][\"PerSurface\"][\"Q_e\"]))\n", + " # plot balance vs q with bcrit as vertical line\n", + " p2 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2,xlim=(-.2,.2),ylim=(-1e-2,1e-2))\n", + " plot!(p2, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", + " xlabel!(p2, \"Q\")\n", + " ylabel!(p2, \"balance\")\n", + " title!(p2, \"2P(Q0-Q)/jxb - surface $(surface_num)\")\n", + " #vline!(p2, [read(file[\"Tearing\"][\"CriticalResonantField\"][\"br_crit\"])], label=\"bcrit\", lw=2, lc=:red)\n", + " # add Q_e as vertical line\n", + " vline!(p2, [read(file[\"Tearing\"][\"PerSurface\"][\"Q_e\"])[surface_num]], label=\"Q_e\", lw=2, lc=:green)\n", + " vline!(p2, [read(file[\"Tearing\"][\"PerSurface\"][\"Q_i\"])[surface_num]], label=\"Q_i\", lw=2, lc=:blue)\n", + " vline!(p2, [read(file[\"Tearing\"][\"CriticalResonantField\"][\"Qpeak\"])[surface_num]], label=\"Qpeak\", lw=2, lc=:orange)\n", + " #display(aplot)\n", + " display(p2)\n", + "\n", + "end\n", + "\n", + "\"\"\"\n", + "Local maxima indices: [104, 103] with values: [80.15320925995013, 79.66428209429431] and corresponding Qs: [0.35175879396984927, 0.25125628140703515] closest Q to Q_e: -0.35175879396984927 closest Q to Q_i: 0.35175879396984927\n", + "Warning: The first local maximum may correspond to an electron or ion diamagnetic resonance. Selecting the second local maximum instead.\n", + "Selected local maximum index: 103 with value: 79.66428209429431 and corresponding Q: 0.25125628140703515\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "10", + "metadata": {}, + "outputs": [], + "source": [ + "# Plot bcrit vs q surface\n", + "\n", + "# print all contents of bcrit /scan /surface 1/\n", + "h5open(h5path, \"r\") do file\n", + " bcrit = file[\"Tearing\"][\"CriticalResonantField\"]\n", + "\n", + " for i in 1:6\n", + " ss = \"surface_$i\"\n", + "\n", + " delta = read(bcrit[\"Scan\"][ss][\"delta\"])\n", + " Q = read(bcrit[\"Scan\"][ss][\"Q\"])\n", + " balance = read(bcrit[\"Scan\"][ss][\"balance\"])\n", + "\n", + " display(bcrit_diag_plots(delta, Q, balance, \"surface_$i\"))\n", + " end\n", + "end" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11", + "metadata": {}, + "outputs": [], + "source": [ + "p_eq = Analysis.Equilibrium.plot_equilibrium_summary(h5path)\n", + "p_ffs = Analysis.ForceFreeStates.plot_ffs_summary(h5path)\n", + "#p_pe = Analysis.PerturbedEquilibrium.plot_perturbed_equilibrium_summary(h5path)\n", + "\n", + "display(p_eq)\n", + "display(p_ffs)\n", + "#display(p_pe)" + ] + } + ], + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/DIIID-like_SLAYER_example/slayer_ex.ipynb b/examples/DIIID-like_SLAYER_example/slayer_ex.ipynb deleted file mode 100644 index 710608340..000000000 --- a/examples/DIIID-like_SLAYER_example/slayer_ex.ipynb +++ /dev/null @@ -1,266 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "0", - "metadata": {}, - "outputs": [], - "source": [ - "using Pkg\n", - "Pkg.activate(\"/Users/bursche/Documents/GitHub/JPEC_BCRIT\")\n", - "Base.active_project()\n", - "\n", - "using GeneralizedPerturbedEquilibrium\n", - "using GeneralizedPerturbedEquilibrium: Analysis\n", - "using Printf\n", - "\n", - "using Plots\n", - "default(\n", - " fontfamily=\"Georgia\",\n", - " margin=12Plots.mm,\n", - " size=(800, 500),\n", - " dpi=150\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1", - "metadata": {}, - "outputs": [], - "source": [ - "h5path = \"/Users/bursche/Documents/GitHub/JPEC_BCRIT/examples/DIIID-like_SLAYER_example/gpec.h5\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2", - "metadata": {}, - "outputs": [], - "source": [ - "using HDF5\n", - "\n", - "h5open(h5path, \"r\") do file\n", - " println(\"Top-level keys:\")\n", - " println(collect(keys(file)))\n", - "\n", - " if haskey(file, \"Tearing\")\n", - " println(\"\\nKeys in Tearing:\")\n", - " println(collect(keys(file[\"Tearing\"])))\n", - "\n", - " if haskey(file[\"Tearing\"], \"CriticalResonantField\")\n", - " println(\"\\nKeys in Tearing/CriticalResonantField:\")\n", - " println(collect(keys(file[\"Tearing\"][\"CriticalResonantField\"])))\n", - " end\n", - " else\n", - " println(\"No Tearing group found.\")\n", - " end\n", - "end" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3", - "metadata": {}, - "outputs": [], - "source": [ - "# Print the contents of the Tearing/CriticalResonantField group\n", - "h5open(h5path, \"r\") do file\n", - " if haskey(file, \"Tearing\") && haskey(file[\"Tearing\"], \"CriticalResonantField\")\n", - " println(\"\\nContents of Tearing/CriticalResonantField:\")\n", - " # Iterate over the keys in the Tearing/CriticalResonantField group and print their names and types\n", - " for key in keys(file[\"Tearing\"][\"CriticalResonantField\"])\n", - " dataset = file[\"Tearing\"][\"CriticalResonantField\"][key]\n", - " println(\"Key: $key, Type: $(typeof(dataset))\")\n", - " # print data \n", - " if isa(dataset, HDF5.Dataset)\n", - " data = read(dataset)\n", - " println(\"Data: $data\")\n", - " end\n", - " end\n", - " else\n", - " println(\"No Tearing/CriticalResonantField group found.\")\n", - " end\n", - " # Print bcrit data as .2e (in one line)\n", - " println(\"\\nBcrit data: $(join([@sprintf(\"%.2e\", x) for x in read(file[\"Tearing\"][\"CriticalResonantField\"][\"br_crit\"])], \" \"))\")\n", - "end\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4", - "metadata": {}, - "outputs": [], - "source": [ - "println(keys(h5open(h5path, \"r\")[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_1\"]))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5", - "metadata": {}, - "outputs": [], - "source": [ - "function bcrit_diag_plots(Δs, Qs, bal,name)\n", - "\n", - " p1 = plot(Qs, imag.(Δs), label=\"Im(Δ)\", lw=2)\n", - " #plot!(p1, Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", - " xlabel!(p1, \"Q\")\n", - " ylabel!(p1, \"Δ\")\n", - " title!(p1, \"Inner-layer Δ(Q) - $name\")\n", - "\n", - " p2 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2)\n", - " plot!(p2, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", - " xlabel!(p2, \"Q\")\n", - " ylabel!(p2, \"balance\")\n", - " title!(p2, \"2P(Q0-Q)/jxb - $name\")\n", - "\n", - " plot(p1, p2, layout=(2,1), size=(800, 1000))\n", - "\n", - "\n", - "end" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6", - "metadata": {}, - "outputs": [], - "source": [ - "# print all P values\n", - "println(\"\\nP values for each surface in the scan:\")\n", - "h5open(h5path, \"r\") do file\n", - " for i in 1:6\n", - " ss = \"surface_$i\"\n", - " if haskey(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"], ss)\n", - " P = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][ss][\"P\"])\n", - " println(\"Surface $i: P = $(join([@sprintf(\"%.2e\", x) for x in P], \" \"))\")\n", - " else\n", - " println(\"Surface $i: No data found.\")\n", - " end\n", - " end\n", - "end\n", - "# want to print chi_tor for each surface in the scan, need to use P = (4π * 1e-7) .* abs.(chi_sel) ./ η_neo, so chi_sel = P * η_neo / (4π * 1e-7)\n", - "println(\"\\nchi_tor values for each surface in the scan:\")\n", - "h5open(h5path, \"r\") do file\n", - " for i in 1:6\n", - " ss = \"surface_$i\"\n", - " if haskey(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"], ss)\n", - " P = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][ss][\"P\"])\n", - " η_neo = read(file[\"Tearing\"][\"PerSurface\"][\"eta\"])\n", - " chi_tor = P .* η_neo[i] ./ (4π * 1e-7)\n", - " println(\"Surface $i: chi_tor = $(join([@sprintf(\"%.2e\", x) for x in chi_tor], \" \"))\") \n", - " else\n", - " println(\"Surface $i: No data found.\")\n", - " end\n", - " end\n", - "end" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7", - "metadata": {}, - "outputs": [], - "source": [ - "# plot jxb vs Qs for surface 1\n", - "# jxbs = [-imag(1.0 / (d + 1e-2)) for d in Δs]\n", - "surface_num = 2\n", - "h5open(h5path, \"r\") do file\n", - " Δs = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"delta\"])\n", - " Qs = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"Q\"])\n", - " bal = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"balance\"])\n", - " jxbs = [-imag(1.0 / (d + 1e-2)) for d in Δs]\n", - " aplot = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", - " xlabel!(\"Q\")\n", - " ylabel!(\"jxb\")\n", - " title!(\"jxb vs Q for surface $(surface_num)\")\n", - " println(\"max of balance: \", maximum(bal))\n", - " println(\"max of jxb: \", maximum(jxbs))\n", - " println(\"bcrit: \", read(file[\"Tearing\"][\"CriticalResonantField\"][\"br_crit\"]))\n", - " println(\"Qpeak: \", read(file[\"Tearing\"][\"CriticalResonantField\"][\"Qpeak\"]))\n", - " println(\"Q_e: \", read(file[\"Tearing\"][\"PerSurface\"][\"Q_e\"]))\n", - " # plot balance vs q with bcrit as vertical line\n", - " p2 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2)\n", - " plot!(p2, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", - " xlabel!(p2, \"Q\")\n", - " ylabel!(p2, \"balance\")\n", - " title!(p2, \"2P(Q0-Q)/jxb - surface $(surface_num)\")\n", - " vline!(p2, [read(file[\"Tearing\"][\"CriticalResonantField\"][\"br_crit\"])], label=\"bcrit\", lw=2, lc=:red)\n", - " # add Q_e as vertical line\n", - " vline!(p2, [read(file[\"Tearing\"][\"PerSurface\"][\"Q_e\"])[surface_num]], label=\"Q_e\", lw=2, lc=:green)\n", - " vline!(p2, [read(file[\"Tearing\"][\"PerSurface\"][\"Q_i\"])[surface_num]], label=\"Q_i\", lw=2, lc=:blue)\n", - "\n", - " display(aplot)\n", - " display(p2)\n", - "\n", - "end\n", - "\n", - "\"\"\"\n", - "Local maxima indices: [104, 103] with values: [80.15320925995013, 79.66428209429431] and corresponding Qs: [0.35175879396984927, 0.25125628140703515] closest Q to Q_e: -0.35175879396984927 closest Q to Q_i: 0.35175879396984927\n", - "Warning: The first local maximum may correspond to an electron or ion diamagnetic resonance. Selecting the second local maximum instead.\n", - "Selected local maximum index: 103 with value: 79.66428209429431 and corresponding Q: 0.25125628140703515\n", - "\"\"\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8", - "metadata": {}, - "outputs": [], - "source": [ - "# Plot bcrit vs q surface\n", - "\n", - "# print all contents of bcrit /scan /surface 1/\n", - "h5open(h5path, \"r\") do file\n", - " bcrit = file[\"Tearing\"][\"CriticalResonantField\"]\n", - "\n", - " for i in 1:6\n", - " ss = \"surface_$i\"\n", - "\n", - " delta = read(bcrit[\"Scan\"][ss][\"delta\"])\n", - " Q = read(bcrit[\"Scan\"][ss][\"Q\"])\n", - " balance = read(bcrit[\"Scan\"][ss][\"balance\"])\n", - "\n", - " display(bcrit_diag_plots(delta, Q, balance, \"surface_$i\"))\n", - " end\n", - "end" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9", - "metadata": {}, - "outputs": [], - "source": [ - "p_eq = Analysis.Equilibrium.plot_equilibrium_summary(h5path)\n", - "p_ffs = Analysis.ForceFreeStates.plot_ffs_summary(h5path)\n", - "#p_pe = Analysis.PerturbedEquilibrium.plot_perturbed_equilibrium_summary(h5path)\n", - "\n", - "display(p_eq)\n", - "display(p_ffs)\n", - "#display(p_pe)" - ] - } - ], - "metadata": { - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/src/Tearing/CriticalResonantField/CRF Dev/P_eta_calc.ipynb b/src/Tearing/CriticalResonantField/CRF Dev/P_eta_calc.ipynb deleted file mode 100644 index 0639317bd..000000000 --- a/src/Tearing/CriticalResonantField/CRF Dev/P_eta_calc.ipynb +++ /dev/null @@ -1,279 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "0", - "metadata": {}, - "outputs": [], - "source": [ - "using Pkg\n", - "Pkg.activate(\"/Users/bursche/Documents/GitHub/JPEC_BCRIT\")\n", - "Base.active_project()\n", - "\n", - "using Plots\n", - "using Printf" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1", - "metadata": {}, - "outputs": [], - "source": [ - "# Minimal Julia implementation of the `neo_2021` branch.\n", - "\n", - "# Inputs:\n", - "# Te : electron temperature [eV]\n", - "# ne : electron density [m^-3]\n", - "# Ti : ion temperature [eV]\n", - "# q : safety factor\n", - "# eps : inverse aspect ratio\n", - "# R : major radius [m]\n", - "# fT : trapped-particle fraction\n", - "# Zeff : effective charge\n", - "\n", - "# Output:\n", - "# σ_spitzer : Spitzer conductivity [1/(Ω m)]\n", - "# σ_neo : Redl 2021 neoclassical conductivity [1/(Ω m)]\n", - "\n", - "# All inputs can be scalars or arrays of the same size.\n", - "\n", - "function neoclassical_conductivity(\n", - " Te, ne, Ti, q, eps, R, fT, Zeff;\n", - " version = :neo_2021,\n", - ")\n", - "\n", - " # Coulomb logarithms\n", - " lnΛe = 23.5 .-\n", - " log.(sqrt.(ne ./ 1e6) .* Te.^(-5/4)) .-\n", - " sqrt.(1e-5 .+ (log.(Te) .- 2).^2 ./ 16)\n", - "\n", - " # Ion density.\n", - " #\n", - " # For the simple D + C model used in the original code:\n", - " # n_i = n_main + n_imp\n", - " #\n", - " # If only Zeff is supplied, the original function uses\n", - " # n_i = ne / Zeff\n", - " ni = ne ./ Zeff\n", - "\n", - " # With only Zeff available, Zdom = 1, giving\n", - " Zdom = 1.0\n", - "\n", - " # Average ion charge\n", - " Zavg = ne ./ ni\n", - "\n", - " # Koh effective ion charge\n", - " Zion = (Zdom^2 .* Zavg .* Zeff).^(1/4)\n", - "\n", - " # Ion Coulomb logarithm\n", - " lnΛi = 30.0 .-\n", - " log.(Zion.^3 .* sqrt.(ni) ./ Ti.^1.5)\n", - "\n", - " # Prevent pathological negative electron Coulomb logarithms\n", - " lnΛe_min = minimum(lnΛe[lnΛe .> 0])\n", - " lnΛe = max.(lnΛe, lnΛe_min)\n", - "\n", - " # Avoid eps = 0\n", - " eps_nz = copy(eps)\n", - " if any(eps .== 0)\n", - " eps_nz[eps .== 0] .= minimum(eps[eps .!= 0])\n", - " end\n", - "\n", - " # Electron collisionality, Eq. 18b\n", - " νe_star = 6.921e-18 .* abs.(q) .* R .* ne .* Zeff .* lnΛe ./\n", - " (Te.^2 .* eps_nz.^1.5)\n", - "\n", - " # Ion collisionality, Eq. 18c\n", - " νi_star = 4.90e-18 .* abs.(q) .* R .* ni .* Zion.^4 .* lnΛi ./\n", - " (Ti.^2 .* eps_nz.^1.5)\n", - "\n", - " # Sauter Eq. 18a\n", - " NZ(Z) = 0.58 + 0.74 ./ (0.76 + Z)\n", - "\n", - " σ_spitzer = 1.9012e4 .* Te.^1.5 ./\n", - " (Zeff .* NZ(Zeff) .* lnΛe)\n", - "\n", - " # Redl 2021, Eq. 18\n", - " f33teff = fT ./ (\n", - " 1 .+\n", - " 0.25 .* (1 .- 0.7 .* fT) .* sqrt.(νe_star) .*\n", - " (1 .+ 0.45 .* sqrt.(Zeff .- 1)) .+\n", - " 0.61 .* (1 .- 0.41 .* fT) .* νe_star ./ sqrt.(Zeff)\n", - " )\n", - "\n", - " # Redl 2021, Eq. 17\n", - " F33 = 1 .-\n", - " (1 .+ 0.21 ./ Zeff) .* f33teff .+\n", - " 0.54 ./ Zeff .* f33teff.^2 .-\n", - " 0.33 ./ Zeff .* f33teff.^3\n", - "\n", - " σ_neo = σ_spitzer .* F33\n", - "\n", - " return σ_neo, σ_spitzer\n", - "end" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2", - "metadata": {}, - "outputs": [], - "source": [ - "function calc_resistivity_P(chi, ne, Te, Zeff, q, eps, R, fT, volume;\n", - " model=:neoclassical)\n", - " cond = neoclassical_conductivity(\n", - " Te=Te,\n", - " ne=ne,\n", - " Ti=Te,\n", - " Zeff=Zeff,\n", - " q=q,\n", - " eps=eps,\n", - " R=R,\n", - " fT=fT,\n", - " volume=volume,\n", - " version=:neo_2021,\n", - " )\n", - "\n", - " σ = model == :neoclassical ?\n", - " cond.neoclassical_conductivity :\n", - " cond.spitzer_conductivity\n", - "\n", - " η = 1 ./ σ\n", - " P = (4π * 1e-7) .* abs.(chi) ./ η\n", - "\n", - " return η, P\n", - "end" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3", - "metadata": {}, - "outputs": [], - "source": [ - "σ_neo, σ_spitzer = neoclassical_conductivity(\n", - " Te_eV,\n", - " ne_sel,\n", - " Te_eV, # Ti = Te\n", - " qsing,\n", - " eps_sel,\n", - " R_sel,\n", - " fT_sel;\n", - " Zeff=zeff_sel,\n", - ")\n", - "\n", - "η_neo = 1.0 ./ σ_neo\n", - "η_spitzer = 1.0 ./ σ_spitzer\n", - "\n", - "P = (4π * 1e-7) .* abs.(chi_sel) ./ η_neo" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4", - "metadata": {}, - "outputs": [], - "source": [ - "σ_neo, σ_spitzer = neoclassical_conductivity(\n", - " 106.211805100300, # Te [eV]\n", - " 1.005827348013049e19, # ne [m^-3]\n", - " 106.211805100300, # Ti [eV]\n", - " 6.00000000000048, # q\n", - " 0.771873939341347 / 1.74333594120074, # eps = rs / R0\n", - " 1.74333594120074, # R [m]\n", - " 1, #fT; # trapped fraction\n", - " 1.80427095488192, # Zeff\n", - ")\n", - "\n", - "η_neo = 1.0 ./ σ_neo\n", - "η_spitzer = 1.0 ./ σ_spitzer\n", - "\n", - "chi_sel = 1\n", - "\n", - "P = (4π * 1e-7) .* abs.(chi_sel) ./ η_neo" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5", - "metadata": {}, - "outputs": [], - "source": [ - "using LinearAlgebra # or relevant module providing neoclassical_conductivity\n", - "\n", - "# --- Set 1 Inputs (5 radial points) ---\n", - "Te_eV = [718.04269217, 342.58020426, 188.39435197, 95.70267912, 44.04668565] # Te and Ti [eV]\n", - "ne_sel = [1.98796958e19, 1.80371630e19, 1.55527262e19, 1.23649097e19, 8.97867646e18] # ne [m^-3]\n", - "zeff_sel = [1.65619282, 1.64427584, 1.58198407, 1.55990923, 1.68572562] # Zeff\n", - "qsing = [2.0, 3.0, 4.0, 5.0, 6.0] # q\n", - "eps_sel = [0.22284171, 0.28956909, 0.32302672, 0.34432513, 0.35141583] # eps = r/R\n", - "R_sel = [1.72151657, 1.70693349, 1.69832026, 1.69192129, 1.68947514] # R [m]\n", - "fT_sel = [0.6127298, 0.66890766, 0.68553652, 0.68355803, 0.67414449] # Trapped fraction fT\n", - "\n", - "# Reference values from Python NCLASS run (for validation)\n", - "py_neo = [7683580.66632273, 3011088.07938057, 1644303.89021149, 782055.27991453, 274193.4323623]\n", - "py_spitzer = [16324797.88300323, 5666135.22162908, 2468477.31865855, 941040.7938515, 290205.76181926]\n", - "\n", - "# --- Run Neoclassical Conductivity in Julia ---\n", - "# Broadcasting across all 5 radial positions:\n", - "σ_neo, σ_spitzer = neoclassical_conductivity.(\n", - " Te_eV, # Te [eV]\n", - " ne_sel, # ne [m^-3]\n", - " Te_eV, # Ti [eV] (assumed Ti = Te)\n", - " qsing, # q\n", - " eps_sel, # eps\n", - " R_sel, # R [m]\n", - " fT_sel, # trapped fraction fT\n", - " zeff_sel # Zeff\n", - ")\n", - "\n", - "# Collect tuple outputs into a vector of tuples\n", - "results = [\n", - " neoclassical_conductivity(\n", - " Te_eV[i], ne_sel[i], Te_eV[i], qsing[i], \n", - " eps_sel[i], R_sel[i], fT_sel[i], zeff_sel[i]\n", - " ) for i in 1:length(Te_eV)\n", - "]\n", - "\n", - "# Extract σ_neo (1st element) and σ_spitzer (2nd element)\n", - "σ_neo = getindex.(results, 1)\n", - "σ_spitzer = getindex.(results, 2)\n", - "\n", - "η_neo = 1.0 ./ σ_neo\n", - "η_spitzer = 1.0 ./ σ_spitzer\n", - "\n", - "chi_sel = 1\n", - "P = (4π * 1e-7) .* abs.(chi_sel) ./ η_neo\n", - "\n", - "\n", - "# --- Comparison Printouts ---\n", - "println(\"=== Neoclassical Conductivity Comparison ===\")\n", - "for i in 1:length(Te_eV)\n", - " println(\"Point $i (q=$(qsing[i])):\")\n", - " println(\" Julia σ_neo : \", σ_neo[i])\n", - " println(\" Python σ_neo : \", py_neo[i])\n", - " println(\" Julia σ_spitzer : \", σ_spitzer[i])\n", - " println(\" Python σ_spitzer: \", py_spitzer[i])\n", - " println(\" P (magnetic diff): \", P[i])\n", - " println()\n", - "end" - ] - } - ], - "metadata": { - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/src/Tearing/CriticalResonantField/CRF Dev/b_crit.jls b/src/Tearing/CriticalResonantField/CRF Dev/b_crit.jls deleted file mode 100644 index dcd8e2611787cf2ae06b76a1ee64426e4009ac8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74 zcmXr_@{waLoNTscITzal0AxrQ1ONa4 diff --git a/src/Tearing/CriticalResonantField/CRF Dev/bcrit_dev.ipynb b/src/Tearing/CriticalResonantField/CRF Dev/bcrit_dev.ipynb deleted file mode 100644 index 5f9dfac2a..000000000 --- a/src/Tearing/CriticalResonantField/CRF Dev/bcrit_dev.ipynb +++ /dev/null @@ -1,724 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "0", - "metadata": {}, - "outputs": [], - "source": [ - "using Pkg\n", - "Pkg.activate(\"/Users/bursche/Documents/GitHub/JPEC_BCRIT\")\n", - "Base.active_project()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1", - "metadata": {}, - "outputs": [], - "source": [ - "using GeneralizedPerturbedEquilibrium\n", - "using GeneralizedPerturbedEquilibrium: Analysis\n", - "using GeneralizedPerturbedEquilibrium: InnerLayer\n", - "using GeneralizedPerturbedEquilibrium.InnerLayer: solve_inner\n", - "using GeneralizedPerturbedEquilibrium: Tearing\n", - "using ..InnerLayer\n", - "using ..InnerLayer: InnerLayerModel, solve_inner, GGJModel, GGJParameters,\n", - " SLAYERModel, SLAYERParameters\n", - "\n", - "using Plots\n", - "using Printf\n", - "default(\n", - " fontfamily=\"Georgia\",\n", - " margin=12Plots.mm,\n", - " size=(800, 500),\n", - " dpi=150\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2", - "metadata": {}, - "outputs": [], - "source": [ - "struct TorqueBalance{M<:InnerLayerModel,P}\n", - " model::M\n", - " params::P\n", - " Q0::Float64\n", - " P::Float64\n", - " lu::Float64\n", - " sval::Float64\n", - "end\n", - "\n", - "function torque_balance_value(tb::TorqueBalance, Q::Number)\n", - " Δ = solve_inner(tb.model, tb.params, ComplexF64(Q)).tearing\n", - " alpha = 1e-2\n", - " jxb = -imag(1.0 / (Δ+ alpha))\n", - " return 2.0 * tb.P * (tb.Q0 - Q) / jxb, Δ\n", - "end\n", - "\n", - "function torque_balance_scan(tb; Qmin=-10.0, Qmax=10.0, n=200)\n", - " Qs = range(Qmin, Qmax; length=n)\n", - " torque_out = [torque_balance_value(tb, q) for q in Qs]\n", - " bal = [x[1] for x in torque_out]\n", - " Δs = [x[2] for x in torque_out]\n", - " #bal = [torque_balance_value(tb, q) for q in Qs]\n", - " positive = isfinite.(bal) .& (bal .> 0.0)\n", - "\n", - " if !any(positive)\n", - " return Qs, bal, NaN, NaN, 0.0, NaN, NaN, Δs\n", - " end\n", - " i = argmax(bal)\n", - " Qpeak_ind = i\n", - " Qs_positive = Qs[positive]\n", - " bal_positive = bal[positive]\n", - "\n", - " i = argmax(bal_positive)\n", - " Qpeak = Qs_positive[i]\n", - " \n", - " maxbal = bal_positive[i]\n", - "\n", - " br_crit = sqrt(maxbal / tb.lu * (tb.sval^2 / 2.0))\n", - " return Qs, bal, Qs_positive, bal_positive, Qpeak, br_crit, Qpeak_ind, Δs\n", - "end" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3", - "metadata": {}, - "outputs": [], - "source": [ - "p = GeneralizedPerturbedEquilibrium.InnerLayer.slayer_parameters(\n", - " n_e=1e19, t_e=1e3, t_i=1e3,\n", - " omega=0.0, omega_e=4, omega_i=-2,\n", - " qval=2.0, sval_r=0.5, bt=2.0, rs=1.0, R0=3.0, mu_i=2.0, zeff=1.0,\n", - " chi_perp=1.0, chi_tor=1.0, m=2, n=1\n", - ")\n", - "p2 = GeneralizedPerturbedEquilibrium.InnerLayer.SLAYERParameters(\n", - " ising=p.ising,\n", - " m=p.m, n=p.n,\n", - " tau=p.tau, lu=p.lu, c_beta=p.c_beta, D_norm=p.D_norm,\n", - " P_perp=p.P_perp, P_tor=p.P_tor,\n", - " Q_e=0.818, Q_i=-0.543, iota_e=p.iota_e,\n", - " tauk=p.tauk, tau_r=p.tau_r, delta_n=p.delta_n,\n", - " rs=p.rs, R0=p.R0, bt=p.bt, sval_r=p.sval_r,\n", - " dr_val=p.dr_val, dgeo_val=p.dgeo_val,\n", - " eta=p.eta, d_beta=p.d_beta,\n", - " dc_tmp=p.dc_tmp, dc_type=p.dc_type\n", - ")\n", - "\n", - "p2 = GeneralizedPerturbedEquilibrium.InnerLayer.SLAYERParameters(\n", - " ising=p.ising,\n", - " m=p.m, n=p.n,\n", - " tau=p.tau, lu=p.lu, c_beta=p.c_beta, D_norm=p.D_norm,\n", - " P_perp=p.P_perp, P_tor=p.P_tor,\n", - " Q_e=2, Q_i=3, iota_e=p.iota_e,\n", - " tauk=p.tauk, tau_r=p.tau_r, delta_n=p.delta_n,\n", - " rs=p.rs, R0=p.R0, bt=p.bt, sval_r=p.sval_r,\n", - " dr_val=p.dr_val, dgeo_val=p.dgeo_val,\n", - " eta=p.eta, d_beta=p.d_beta,\n", - " dc_tmp=p.dc_tmp, dc_type=p.dc_type\n", - ")\n", - "\n", - "p = p2\n", - "\n", - "tb = TorqueBalance(\n", - " GeneralizedPerturbedEquilibrium.InnerLayer.SLAYERModel(;),\n", - " p,\n", - " 0.5,\n", - " p.P_tor,\n", - " p.lu,\n", - " p.sval_r\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4", - "metadata": {}, - "outputs": [], - "source": [ - "#Qs = range(-5.0, 5.0, length=200)\n", - "\n", - "#vals = [torque_balance_value(tb, q) for q in Qs]\n", - "\"\"\"\n", - "n=2000:\n", - "Qpeak = 0.24512256128064033\n", - "maxbal = 0.35873684252530247\n", - "br_crit = 4.668551985584323e-5\n", - "\n", - "n=200 (def):\n", - "Qpeak = 0.25125628140703515\n", - "maxbal = 0.3585219071071706\n", - "br_crit = 4.667153206033017e-5\n", - "\"\"\"\n", - "Qmi = -10\n", - "Qma = 10\n", - "\n", - "Qs, bal, Qs_positive, bal_positive, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb,Qmin=Qmi, Qmax=Qma, n=100)\n", - "\n", - "println(\"Qpeak = \", Qpeak)\n", - "println(\"maxbal = \", maximum(bal_positive))\n", - "println(\"maxbal = \", maximum(bal))\n", - "println(\"br_crit = \", brcrit)\n", - "\n", - "p1 = plot(Qs, bal, lw=2, label=\"balance\")#,ylim=(-40, 40))\n", - "z_inds = findall(i -> bal[i]*bal[i+1] < 0, 1:length(bal)-1)\n", - "println(\"zero crossings at Q = \", Qs[z_inds])\n", - "for i in z_inds\n", - " vline!([Qs[i]], label=\"0\", linestyle=:dot, color=:gray)\n", - "end\n", - "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", - "xlabel!(\"Q\")\n", - "ylabel!(\"balance\")\n", - "title!(\"Torque-balance scan\")\n", - "\n", - "\n", - "\n", - "p5 = plot(Qs, bal, lw=2, label=\"balance\",xlim=(Qs[z_inds[1]],Qs[z_inds[2]]))#,ylim=(-40, 40))#, xlim = (-.11,-.09))\n", - "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", - "xlabel!(\"Q\")\n", - "ylabel!(\"balance\")\n", - "title!(\"Torque-balance scan\")\n", - "\n", - "p2 = plot(Qs, -imag(Δs), lw=2, label=\"Im(Δ)\",ylim=(-5,2))#,xlim=(-.11,-.09))\n", - "plot!(p2, Qs, real(Δs), lw=2, label=\"Re(Δ)\")\n", - "#vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - "#hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", - "vline!([-3], linestyle=:dashdot)\n", - "vline!([-2], linestyle=:dashdot)\n", - "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - "vline!([0.499], linestyle=:dashdot)\n", - "xlabel!(\"Q\")\n", - "ylabel!(\"Δ\")\n", - "title!(\"Torque-balance scan\")\n", - "\n", - "jxb = -imag(1.0 ./ (Δs .+ 1e-2))\n", - "jxb0 = -imag(1.0 ./ (Δs))\n", - "p3 = plot(Qs, jxb, lw=2, label=\"-Im(1 / (Δs + 1e-2))\",color=:blue)#, xlim = (-.11,-.09),ylim=(-500,500))\n", - "plot!(p3, Qs, jxb0, lw=2, label=\"-Im(1 / Δs)\",color=:red,linestyle=:dash)\n", - "xlabel!(\"Q\")\n", - "ylabel!(\"~ jxb\")\n", - "\n", - "p4 = plot(Qs, jxb, lw=2, label=\"-Im(1 / Δs)\",color=:blue)#, xlim = (-.11,-.09))\n", - "xlabel!(\"Q\")\n", - "ylabel!(\"~ jxb\")\n", - "\"\"\"\n", - "#remake plot 1 but of derivative of balance with respect to Q\n", - "dQ = Qs[2] - Qs[1]\n", - "dbal_dQ = diff(bal) ./ dQ\n", - "p3 = plot(Qs[1:end-1], dbal_dQ, lw=2, label=\"d(balance)/dQ\",ylim=(-1000, 1000))\n", - "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", - "xlabel!(\"Q\")\n", - "ylabel!(\"d(balance)/dQ\")\n", - "\"\"\"\n", - "\n", - "Qs, bal, Qs_positive, bal_positive, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb,Qmin=Qs[], Qmax=Qs[zin], n=10000)\n", - "\n", - "\n", - "plo = plot(p1, p2,p3,p4,p5, p6, layout=(6,1), size=(1000, 2000))\n", - "display(plo)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5", - "metadata": {}, - "outputs": [], - "source": [ - "Qlow = -0.1005100510051005\n", - "Qhigh = 0.49954995499549953\n", - "\n", - "#Qs, bal, Qs_positive, bal_positive, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb,Qmin=Qlow, Qmax=Qhigh, n=10000)\n", - "\n", - "println(\"Qpeak = \", Qpeak)\n", - "println(\"maxbal = \", maximum(bal_positive))\n", - "println(\"maxbal = \", maximum(bal))\n", - "println(\"br_crit = \", brcrit)\n", - "\n", - "p1 = plot(Qs, bal, lw=2, label=\"balance\")#,ylim=(-40, 40))\n", - "z_inds = findall(i -> bal[i]*bal[i+1] < 0, 1:length(bal)-1)\n", - "println(\"zero crossings at Q = \", Qs[z_inds])\n", - "for i in z_inds\n", - " vline!([Qs[i]], label=\"0\", linestyle=:dot, color=:gray)\n", - "end\n", - "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", - "xlabel!(\"Q\")\n", - "ylabel!(\"balance\")\n", - "title!(\"Torque-balance scan\")\n", - "\n", - "\n", - "p5 = plot(Qs, bal, lw=2, label=\"balance\",ylim=(-40, 40), xlim = (-.11,-.09))\n", - "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", - "xlabel!(\"Q\")\n", - "ylabel!(\"balance\")\n", - "title!(\"Torque-balance scan\")\n", - "\n", - "p2 = plot(Qs, -imag(Δs), lw=2, label=\"Im(Δ)\",ylim=(-2,2))#,xlim=(-.11,-.09))\n", - "plot!(p2, Qs, real(Δs), lw=2, label=\"Re(Δ)\")\n", - "#vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - "#hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", - "xlabel!(\"Q\")\n", - "ylabel!(\"Δ\")\n", - "title!(\"Torque-balance scan\")\n", - "\n", - "jxb = -imag(1.0 ./ (Δs .+ 1e-2))\n", - "jxb0 = -imag(1.0 ./ (Δs))\n", - "p3 = plot(Qs, jxb, lw=2, label=\"-Im(1 / (Δs + 1e-2))\",color=:blue, xlim = (-.11,-.09),ylim=(-500,500))\n", - "plot!(p3, Qs, jxb0, lw=2, label=\"-Im(1 / Δs)\",color=:red,linestyle=:dash)\n", - "xlabel!(\"Q\")\n", - "ylabel!(\"~ jxb\")\n", - "\n", - "p4 = plot(Qs, jxb, lw=2, label=\"-Im(1 / Δs)\",color=:blue, xlim = (-.11,-.09))\n", - "xlabel!(\"Q\")\n", - "ylabel!(\"~ jxb\")\n", - "\"\"\"\n", - "#remake plot 1 but of derivative of balance with respect to Q\n", - "dQ = Qs[2] - Qs[1]\n", - "dbal_dQ = diff(bal) ./ dQ\n", - "p3 = plot(Qs[1:end-1], dbal_dQ, lw=2, label=\"d(balance)/dQ\",ylim=(-1000, 1000))\n", - "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", - "xlabel!(\"Q\")\n", - "ylabel!(\"d(balance)/dQ\")\n", - "\"\"\"\n", - "plo = plot(p1, p2,p3,p4,p5, layout=(5,1), size=(1000, 2000))\n", - "display(plo)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6", - "metadata": {}, - "outputs": [], - "source": [ - "#Qs = range(-5.0, 5.0, length=200)\n", - "\n", - "#vals = [torque_balance_value(tb, q) for q in Qs]\n", - "\"\"\"\n", - "n=2000:\n", - "Qpeak = 0.24512256128064033\n", - "maxbal = 0.35873684252530247\n", - "br_crit = 4.668551985584323e-5\n", - "\n", - "n=200 (def):\n", - "Qpeak = 0.25125628140703515\n", - "maxbal = 0.3585219071071706\n", - "br_crit = 4.667153206033017e-5\n", - "\"\"\"\n", - "\n", - "#Qs, bal, Qs_positive, bal_positive, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb,Qmin=-.2, Qmax=0.5, n=10000)\n", - "\n", - "println(\"Qpeak = \", Qpeak)\n", - "println(\"maxbal = \", maximum(bal_positive))\n", - "println(\"maxbal = \", maximum(bal))\n", - "println(\"br_crit = \", brcrit)\n", - "\n", - "p1 = plot(Qs, bal, lw=2, label=\"balance\")#,ylim=(-40, 40))\n", - "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", - "xlabel!(\"Q\")\n", - "ylabel!(\"balance\")\n", - "title!(\"Torque-balance scan\")\n", - "\n", - "p2 = plot(Qs, -imag(Δs), lw=2, label=\"Im(Δs)\")#,ylim=(-.2,.05))#,xlim=(-.11,-.09))\n", - "plot!(p2, Qs, real(Δs), lw=2, label=\"Re(Δs)\")\n", - "#vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - "#hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", - "xlabel!(\"Q\")\n", - "ylabel!(\"Δs\")\n", - "title!(\"Torque-balance scan\")\n", - "\n", - "\"\"\"\n", - "#remake plot 1 but of derivative of balance with respect to Q\n", - "dQ = Qs[2] - Qs[1]\n", - "dbal_dQ = diff(bal) ./ dQ\n", - "p3 = plot(Qs[1:end-1], dbal_dQ, lw=2, label=\"d(balance)/dQ\",ylim=(-1000, 1000))\n", - "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - "hline!([0.0], label=\"zero\", linestyle=:dashdot)\n", - "xlabel!(\"Q\")\n", - "ylabel!(\"d(balance)/dQ\")\n", - "\"\"\"\n", - "plo = plot(p1, p2, layout=(2,1), size=(800, 1000))\n", - "display(plo)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7", - "metadata": {}, - "outputs": [], - "source": [ - "jxbs = [-imag(1.0 / (d + 1e-2)) for d in Δs]\n", - "\n", - "p1 = plot(Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", - "plot!(p1, Qs, imag.(Δs), label=\"Im(Δ)\", lw=2)\n", - "xlabel!(p1, \"Q\")\n", - "ylabel!(p1, \"Δ\")\n", - "title!(p1, \"Inner-layer Δ(Q)\")\n", - "\n", - "p2 = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", - "xlabel!(p2, \"Q\")\n", - "ylabel!(p2, \"jxb\")\n", - "title!(p2, \"jxb(Q) = -Im[1/(Δ + δ_n_p)]\")\n", - "\n", - "p3 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2)\n", - "plot!(p3, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", - "xlabel!(p3, \"Q\")\n", - "ylabel!(p3, \"balance\")\n", - "title!(p3, \"2P(Q0-Q)/jxb\")\n", - "\n", - "plot(p1, p2, p3, layout=(3,1), size=(800, 1000))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8", - "metadata": {}, - "outputs": [], - "source": [ - "# Check torque is balanced\n", - "\n", - "viscous_torque = 2*tb.P*(tb.Q0 - Qpeak)\n", - "electromagnetic_torque = -imag(1.0 / (Δs[Qpeak_ind] + 1e-2)) *brcrit^2*tb.lu/(tb.sval^2/2)\n", - "\n", - "# delta_n_p = 1e-2\n", - "# jxb = -imag(1.0 / (Δ + delta_n_p))\n", - "# bal = 2.0 * tb.P * (tb.Q0 - Q) / jxb\n", - "# br_crit = sqrt(maxbal / tb.lu * (tb.sval^2 / 2.0))\n", - "\n", - "@printf(\"br_crit = %.5e\\n\", brcrit)\n", - "@printf(\"viscous_torque = %.5e\\n\", viscous_torque)\n", - "@printf(\"electromagnetic_torque = %.5e\\n\", electromagnetic_torque)\n", - "@printf(\"ratio = %.10f\\n\", viscous_torque / electromagnetic_torque)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9", - "metadata": {}, - "outputs": [], - "source": [ - "Qs_n, bal_n, Qs_positive_n, bal_positive_n, Qpeak_n, brcrit_n, Qpeak_ind_n, Δs_n = torque_balance_scan(tb,Qmin=-3, Qmax=3, n=2)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "10", - "metadata": {}, - "outputs": [], - "source": [ - "sample_number = [2, 3, 4, 5, 10,100,1000]#,10000,100000]#,1000000]\n", - "b_crit = []\n", - "# make dicts to store Qs_n and Δs_n arrays for each sample number\n", - "Qs_n_dict = Dict{Int, Vector{Float64}}()\n", - "bal_n_dict = Dict{Int, Vector{Float64}}()\n", - "for i in sample_number\n", - " Qs_n, bal_n, Qs_positive_n, bal_positive_n, Qpeak_n, brcrit_n, Qpeak_ind_n, Δs_n = torque_balance_scan(tb,Qmin=-3, Qmax=3, n=i)\n", - " push!(b_crit, brcrit_n)\n", - " push!(Qs_n_dict, i => Qs_n)\n", - " push!(bal_n_dict, i => bal_n)\n", - " println(bal_n)\n", - "end\n", - "\n", - "# add bcrit = 3.50601e-03 for n=100000 to b_crit\n", - "#push!(b_crit, 3.50601e-03)\n", - "\n", - "# make a plot of b_crit vs sample_number \n", - "p1 = plot(sample_number, b_crit,\n", - " lw=2,\n", - " label=\"b_crit\",\n", - " #xscale=:log10,\n", - " #yscale=:log10,\n", - " xlabel=\"Sample Number\",\n", - " ylabel=\"b_crit\")\n", - "\n", - "p2 = plot(\n", - " xlabel=\"Q\",\n", - " ylabel=\"balance\",\n", - " title=\"Torque balance vs Q\"\n", - ")\n", - "\n", - "for i in sample_number[1:end-1]\n", - " plot!(p2, Qs_n_dict[i], bal_n_dict[i],\n", - " lw=2,\n", - " label=\"n=$i\")\n", - "end\n", - "\n", - "p3 = plot(layout=(3, 2), size=(1000, 800))\n", - "\n", - "for (k, i) in enumerate(sample_number[1:end-1])\n", - " plot!(\n", - " p3[k],\n", - " Qs_n_dict[i],\n", - " bal_n_dict[i],\n", - " lw=2,\n", - " label=\"n=$i\",\n", - " xlabel=\"Q\",\n", - " ylabel=\"balance\",\n", - " title=\"n = $i\"\n", - " )\n", - "end\n", - "\n", - "display(p1)\n", - "display(p2)\n", - "display(p3)\n", - "\n", - "\n", - "println(\"b_crit = \", b_crit)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "11", - "metadata": {}, - "outputs": [], - "source": [ - "println(b_crit)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "12", - "metadata": {}, - "outputs": [], - "source": [ - "bcrit = Any[0.0014075170156654356, 0.0015190532807794722, 0.0015297173529485084, 0.0015297510027746748, 0.0015297613496804952, 0.0015297692159317363, 0.004702965572292843]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "13", - "metadata": {}, - "outputs": [], - "source": [ - "using Serialization\n", - "\n", - "# serialize(\"Qs_n_dict.jls\", Qs_n_dict)\n", - "# serialize(\"bal_n_dict.jls\", bal_n_dict)\n", - "# serialize(\"b_crit.jls\", b_crit)\n", - "# serialize(\"sample_number.jls\", sample_number)\n", - "#my_dict = deserialize(\"my_dict.jls\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "14", - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "Qs, bal, Qs_positive, bal_positive, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb,Qmin=-2.5, Qmax=0, n=20000)\n", - "\n", - "jxbs = [-imag(1.0 / (d + 1e-2)) for d in Δs]\n", - "T_VISC = [2.0 * tb.P * (tb.Q0 - q) for q in Qs] #(q, jxb) in zip(Qs, jxbs)]\n", - "br_t = brcrit\n", - "println(tb.lu, \" \", tb.sval, \" \", br_t, \" \", p.bt, \" \", 1e-2)\n", - "@printf(\"br_crit = %.5e\\n\", brcrit)\n", - "#T_EM = tb.lu * tb.sval^2/2 * (brcrit)^2 * jxbs\n", - "T_EM = -imag(1.0 ./ (Δs .+ 1e-2)) *brcrit^2*tb.lu/(tb.sval^2/2)\n", - "i = Qpeak_ind\n", - "println(T_VISC[i]/(tb.lu * tb.sval^2/2 * (brcrit)^2 * jxbs[i]))\n", - "println(T_VISC[i] / (tb.lu * tb.sval^2/2 * (brcrit * p.bt)^2 * jxbs[i]))\n", - "println(T_VISC[i] / ( (brcrit / p.bt)^2 * jxbs[i]))\n", - "\n", - "#T_EM ∝ S ξ̂ (br/Bφ)² Im[-Δ̂(Q)⁻¹]\n", - "#T_visc ∝ 2 P (Q0 − Q)\n", - "\n", - "xmi = -2.5\n", - "xma = 0\n", - "\n", - "\"\"\"\n", - "p1 = plot(Qs, imag.(Δs), label=\"Im(Δ)\", lw=2, xlim=(xmi, xma))\n", - "#plot!(p1, Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", - "xlabel!(p1, \"Q\")\n", - "ylabel!(p1, \"Δ\")\n", - "#title!(p1, \"Inner-layer Δ(Q)\")\n", - "\"\"\"\n", - "\n", - "p1 = plot( Qs, T_VISC, label=\"T_V\", lw=2, xlim=(xmi, xma))#,ylim=(-1000,1000))\n", - "plot!(p1, Qs, T_EM, label=\"T_EM\", lw=2)\n", - "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - "xlabel!(p1, \"Q\")\n", - "ylabel!(p1, \"Torque\")\n", - "\n", - "#p2 = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", - "p2 = plot( Qs, T_VISC, label=\"T_V\", lw=2, xlim=(xmi, xma))#,ylim=(0,500))\n", - "plot!(p2, Qs, T_EM, label=\"T_EM\", lw=2)\n", - "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - "xlabel!(p2, \"Q\")\n", - "ylabel!(p2, \"Torque\")\n", - "#title!(p2, \"jxb(Q) = -Im[1/(Δ + δ_n_p)]\")\n", - "\n", - "p3 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2, xlim=(xmi, xma))\n", - "plot!(p3, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", - "ylabel!(p3, \"Torque Balance\")\n", - "#title!(p3, \"2P(Q0-Q)/jxb\")\n", - "xlabel!(p3, \"Q\")\n", - "vline!([Qpeak], label=\"Max Balance\", linestyle=:dash)\n", - "\n", - "plot(p1, p2, p3, layout=(3,1), size=(800, 1000))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "15", - "metadata": {}, - "outputs": [], - "source": [ - "# Recreate Cihan's plot:\n", - "\n", - "using Plots\n", - "using DataInterpolations\n", - "\n", - "default(\n", - " fontfamily=\"Georgia\",\n", - " grid=false,\n", - " linewidth=2,\n", - " guidefontsize=26,\n", - " tickfontsize=18,\n", - " titlefontsize=30,\n", - " legendfontsize=18,\n", - " size=(1200, 800),\n", - " dpi=150\n", - ")\n", - "\n", - "# Build the critical boundary bcrit(Q0)\n", - "Q0_scan = range(-1.0, 4.5; length=80)\n", - "bcrit_curve = Float64[]\n", - "\n", - "for Q0 in Q0_scan\n", - " tbQ = TorqueBalance(\n", - " tb.model,\n", - " tb.params,\n", - " Float64(Q0),\n", - " tb.P,\n", - " tb.delta_n_p,\n", - " tb.lu,\n", - " tb.sval\n", - " )\n", - "\n", - " Qs, bal, Qs_pos, bal_pos, Qpeak, brcrit, Qpeak_ind, Δs =\n", - " torque_balance_scan(tbQ; Qmin=-10.0, Qmax=10.0, n=250)\n", - "\n", - " if isempty(bal_pos) || !all(isfinite.(bal_pos)) || maximum(bal_pos) <= 0\n", - " push!(bcrit_curve, NaN)\n", - " else\n", - " push!(bcrit_curve, brcrit)\n", - " end\n", - "end\n", - "\n", - "ok = isfinite.(bcrit_curve)\n", - "Q0_plot = Q0_scan[ok]\n", - "bcrit_plot = bcrit_curve[ok]\n", - "\n", - "perm = sortperm(Q0_plot)\n", - "Q0_plot = Q0_plot[perm]\n", - "bcrit_plot = bcrit_plot[perm]\n", - "\n", - "# Interpolate the boundary: bcrit = f(Q0)\n", - "curve_itp = LinearInterpolation(bcrit_plot, Q0_plot)\n", - "\n", - "# Full phase-box bounds\n", - "x0 = minimum(bcrit_plot) * 0.8\n", - "x1 = maximum(bcrit_plot) * 1.2\n", - "y0 = minimum(Q0_plot)\n", - "y1 = maximum(Q0_plot)\n", - "\n", - "xvals = range(x0, x1; length=350)\n", - "yvals = range(y0, y1; length=350)\n", - "\n", - "locked_mask = zeros(Float64, length(yvals), length(xvals))\n", - "for iy in eachindex(yvals)\n", - " y = yvals[iy]\n", - " for ix in eachindex(xvals)\n", - " x = xvals[ix]\n", - " # locked when bcrit exceeds the boundary for that Q0\n", - " locked_mask[iy, ix] = x >= curve_itp(y) ? 1.0 : 0.0\n", - " end\n", - "end\n", - "\n", - "p = contourf(\n", - " xvals, yvals, locked_mask',\n", - " levels=[-0.5, 0.5, 1.5],\n", - " c=[:navy, :firebrick],\n", - " colorbar=false,\n", - " xlabel=\"b_crit\",\n", - " ylabel=\"Q_0\",\n", - " title=\"Locked / unlocked region\",\n", - " framestyle=:box,\n", - " xlims=(x0, x1),\n", - " ylims=(y0, y1),\n", - " legend=false\n", - ")\n", - "\n", - "# Critical boundary\n", - "plot!(p, bcrit_plot, Q0_plot; lw=3, color=:black, label=\"critical boundary\")\n", - "\n", - "# Critical point\n", - "cp_idx = argmax(bcrit_plot)\n", - "cp_x = bcrit_plot[cp_idx]\n", - "cp_y = Q0_plot[cp_idx]\n", - "scatter!(p, [cp_x], [cp_y]; color=:gold, marker=:star5, ms=12, label=\"critical point\")\n", - "\n", - "# Single legend block with one entry per category\n", - "plot!(p, [NaN], [NaN]; color=:firebrick, lw=4, label=\"locked\")\n", - "plot!(p, [NaN], [NaN]; color=:navy, lw=4, label=\"unlocked\")\n", - "plot!(p, [NaN], [NaN]; color=:black, lw=3, label=\"critical boundary\")\n", - "scatter!(p, [NaN], [NaN]; color=:gold, marker=:star5, ms=12, label=\"critical point\")\n", - "\n", - "plot!(p; legend=:topright)\n", - "\n", - "display(p)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "16", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "17", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/src/Tearing/CriticalResonantField/CRF Dev/bcrit_dev_ggj.ipynb b/src/Tearing/CriticalResonantField/CRF Dev/bcrit_dev_ggj.ipynb deleted file mode 100644 index 617d61585..000000000 --- a/src/Tearing/CriticalResonantField/CRF Dev/bcrit_dev_ggj.ipynb +++ /dev/null @@ -1,298 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "0", - "metadata": {}, - "outputs": [], - "source": [ - "using Pkg\n", - "Pkg.activate(\"/Users/bursche/Documents/GitHub/JPEC_BCRIT\")\n", - "Base.active_project()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1", - "metadata": {}, - "outputs": [], - "source": [ - "using GeneralizedPerturbedEquilibrium\n", - "using GeneralizedPerturbedEquilibrium: GGJParameters\n", - "using GeneralizedPerturbedEquilibrium\n", - "using GeneralizedPerturbedEquilibrium: InnerLayer\n", - "using GeneralizedPerturbedEquilibrium.InnerLayer: solve_inner\n", - "import GeneralizedPerturbedEquilibrium.InnerLayer.GGJ: sfac\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2", - "metadata": {}, - "outputs": [], - "source": [ - "using Plots\n", - "default(\n", - " fontfamily=\"Georgia\",\n", - " margin=12Plots.mm,\n", - " size=(800, 500),\n", - " dpi=150\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3", - "metadata": {}, - "outputs": [], - "source": [ - "struct TorqueBalance\n", - " model\n", - " params\n", - " Q0::Float64\n", - " P::Float64\n", - " delta_n_p::Float64\n", - " lu::Float64\n", - " sval::Float64\n", - "end\n", - "\n", - "function torque_balance_value(tb::TorqueBalance, Q::Number)\n", - " Δ = solve_inner(tb.model, tb.params, ComplexF64(Q)).tearing\n", - " jxb = -imag(1.0 / (Δ + tb.delta_n_p))\n", - " return 2.0 * tb.P * (tb.Q0 - Q) / jxb\n", - "end" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4", - "metadata": {}, - "outputs": [], - "source": [ - "# You can substitute any valid SLAYERParameters you already have.\n", - "# This is just an example skeleton.\n", - "p = GeneralizedPerturbedEquilibrium.InnerLayer.slayer_parameters(\n", - " n_e=1e19, t_e=1e3, t_i=1e3,\n", - " omega=0.0, omega_e=4, omega_i=-2,\n", - " qval=2.0, sval_r=0.5, bt=2.0, rs=1.0, R0=3.0, mu_i=2.0, zeff=1.0,\n", - " chi_perp=1.0, chi_tor=1.0, m=2, n=1\n", - ")\n", - "\n", - "tb = TorqueBalance(\n", - " GeneralizedPerturbedEquilibrium.InnerLayer.SLAYERModel(;),\n", - " p,\n", - " 0.5,\n", - " 1.0,\n", - " 1e-2,\n", - " p.lu,\n", - " p.sval_r\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5", - "metadata": {}, - "outputs": [], - "source": [ - "p_ggj = GeneralizedPerturbedEquilibrium.InnerLayer.glasser_wang_2020_eq55()\n", - "lu_ggj = sfac(p_ggj)\n", - "sval_ggj = 0.5\n", - "\n", - "tb = TorqueBalance(\n", - " GeneralizedPerturbedEquilibrium.InnerLayer.GGJModel(; solver=:galerkin),\n", - " p_ggj,\n", - " 0.5,\n", - " 1.0,\n", - " 1e-2,\n", - " lu_ggj,\n", - " sval_ggj\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6", - "metadata": {}, - "outputs": [], - "source": [ - "\"\"\"\n", - "\n", - "tau_h=R0*(mu0*rho)**0.5/(nns*sval*bt) ! alfven time across surface\n", - "lu=tau_r/tau_h ! Lundquist number\n", - "Qconv=lu**(1.0/3.0)*tau_h ! conversion to Qs based on Cole\n", - "\n", - "! note Q depends on Qconv even if omega is fixed.\n", - "Q=Qconv*omega\n", - "Q_e=-Qconv*omega_e\n", - "Q_i=-Qconv*omega_i\n", - "\n", - "\"\"\"\n", - "2=-lu**(1.0/3.0)*tau_h *OE\n", - "OE = -2 " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7", - "metadata": {}, - "outputs": [], - "source": [ - "Qs = range(-5.0, 5.0, length=20)\n", - "\n", - "vals = [torque_balance_value(tb, q) for q in Qs]\n", - "\n", - "# 1m 34.7s for length = 2\n", - "# 46 m for length = 20\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8", - "metadata": {}, - "outputs": [], - "source": [ - "plot(Qs, real.(vals), label=\"Re(balance)\", lw=2)\n", - "plot!(Qs, imag.(vals), label=\"Im(balance)\", lw=2)\n", - "xlabel!(\"Q\")\n", - "ylabel!(\"torque balance\")\n", - "title!(\"tb(Q)\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9", - "metadata": {}, - "outputs": [], - "source": [ - "Δs = [solve_inner(tb.model, tb.params, ComplexF64(q)).tearing for q in Qs]\n", - "jxbs = [-imag(1.0 / (d + tb.delta_n_p)) for d in Δs]\n", - "\n", - "p1 = plot(Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", - "plot!(p1, Qs, imag.(Δs), label=\"Im(Δ)\", lw=2)\n", - "xlabel!(p1, \"Q\")\n", - "ylabel!(p1, \"Δ\")\n", - "title!(p1, \"Inner-layer Δ(Q)\")\n", - "\n", - "p2 = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", - "xlabel!(p2, \"Q\")\n", - "ylabel!(p2, \"jxb\")\n", - "title!(p2, \"jxb(Q) = -Im[1/(Δ + δ_n_p)]\")\n", - "\n", - "p3 = plot(Qs, real.(vals), label=\"Re(balance)\", lw=2)\n", - "plot!(p3, Qs, imag.(vals), label=\"Im(balance)\", lw=2)\n", - "xlabel!(p3, \"Q\")\n", - "ylabel!(p3, \"balance\")\n", - "title!(p3, \"2P(Q0-Q)/jxb\")\n", - "\n", - "plot(p1, p2, p3, layout=(3,1), size=(800, 1000))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "10", - "metadata": {}, - "outputs": [], - "source": [ - "println(p.lu^(1/3))\n", - "println(p.tauk)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "11", - "metadata": {}, - "outputs": [], - "source": [ - "plt.figure()\n", - "for i in OMFIT['GPEC']['OUTPUTS'].keys():\n", - " try:\n", - " print(OMFIT['GPEC']['OUTPUTS'][i]['DATA'][0]['gpec_slayer_torque_balance_m2_n1_out']['bal'].values)\n", - " plt.plot(OMFIT['GPEC']['OUTPUTS'][i]['DATA'][0]['gpec_slayer_torque_balance_m2_n1_out']['inQ'].values, OMFIT['GPEC']['OUTPUTS'][i]['DATA'][0]['gpec_slayer_torque_balance_m2_n1_out']['bal'].values,label=i)\n", - " except:\n", - " continue\n", - "plt.axhline(0)\n", - "plt.legend()\n", - " \n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "12", - "metadata": {}, - "outputs": [], - "source": [ - "Δs = [solve_inner(tb.model, tb.params, ComplexF64(q)).tearing/p.lu^(1 / 3)/p.rs for q in Qs]\n", - "jxbs = [-imag(1.0 / (d + tb.delta_n_p)) for d in Δs]\n", - "\n", - "p1 = plot(Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", - "plot!(p1, Qs, imag.(Δs), label=\"Im(Δ)\", lw=2)\n", - "xlabel!(p1, \"Q\")\n", - "ylabel!(p1, \"Δ\")\n", - "title!(p1, \"Inner-layer Δ(Q)\")\n", - "\n", - "p2 = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", - "xlabel!(p2, \"Q\")\n", - "ylabel!(p2, \"jxb\")\n", - "title!(p2, \"jxb(Q) = -Im[1/(Δ + δ_n_p)]\")\n", - "\n", - "p3 = plot(Qs, real.(vals), label=\"Re(balance)\", lw=2)\n", - "plot!(p3, Qs, imag.(vals), label=\"Im(balance)\", lw=2)\n", - "xlabel!(p3, \"Q\")\n", - "ylabel!(p3, \"balance\")\n", - "title!(p3, \"2P(Q0-Q)/jxb\")\n", - "\n", - "plot(p1, p2, p3, layout=(3,1), size=(800, 1000))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "13", - "metadata": {}, - "outputs": [], - "source": [ - "p1 = plot(Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", - "plot!(p1, Qs, imag.(Δs), label=\"Im(Δ)\", lw=2)\n", - "xlabel!(p1, \"Q\")\n", - "ylabel!(p1, \"Δ\")\n", - "title!(p1, \"Inner-layer Δ(Q)\")\n", - "\n", - "p2 = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", - "xlabel!(p2, \"Q\")\n", - "ylabel!(p2, \"jxb\")\n", - "title!(p2, \"jxb(Q) = -Im[1/(Δ + δ_n_p)]\")\n", - "\n", - "p3 = plot(Qs, real.(vals), label=\"Re(balance)\", lw=2)\n", - "plot!(p3, Qs, imag.(vals), label=\"Im(balance)\", lw=2)\n", - "xlabel!(p3, \"Q\")\n", - "ylabel!(p3, \"balance\")\n", - "title!(p3, \"2P(Q0-Q)/jxb\")\n", - "\n", - "plot(p1, p2, p3, layout=(3,1), size=(800, 1000))" - ] - } - ], - "metadata": { - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/src/Tearing/CriticalResonantField/CRF Dev/bcrit_numerics.ipynb b/src/Tearing/CriticalResonantField/CRF Dev/bcrit_numerics.ipynb deleted file mode 100644 index 71ed79d9e..000000000 --- a/src/Tearing/CriticalResonantField/CRF Dev/bcrit_numerics.ipynb +++ /dev/null @@ -1,122 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "0", - "metadata": {}, - "outputs": [], - "source": [ - "using Pkg\n", - "Pkg.activate(\"/Users/bursche/Documents/GitHub/JPEC_BCRIT\")\n", - "Base.active_project()\n", - "using GeneralizedPerturbedEquilibrium\n", - "using GeneralizedPerturbedEquilibrium: Analysis\n", - "using GeneralizedPerturbedEquilibrium: InnerLayer\n", - "using GeneralizedPerturbedEquilibrium.InnerLayer: solve_inner\n", - "using GeneralizedPerturbedEquilibrium: Tearing\n", - "using ..InnerLayer\n", - "using ..InnerLayer: InnerLayerModel, solve_inner, GGJModel, GGJParameters,\n", - " SLAYERModel, SLAYERParameters\n", - "using Serialization\n", - "using Plots\n", - "using Printf\n", - "default(\n", - " fontfamily=\"Georgia\",\n", - " margin=12Plots.mm,\n", - " size=(800, 500),\n", - " dpi=150\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1", - "metadata": {}, - "outputs": [], - "source": [ - "bal_n_dict = deserialize(\"bal_n_dict.jls\")\n", - "Qs_n_dict = deserialize(\"Qs_n_dict.jls\")\n", - "sample_number = deserialize(\"sample_number.jls\")\n", - "bcrit = deserialize(\"b_crit.jls\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2", - "metadata": {}, - "outputs": [], - "source": [ - "# make a plot of b_crit vs sample_number \n", - "p1 = plot(\n", - " sample_number,\n", - " b_crit,\n", - " lw=2,\n", - " marker=:circle,\n", - " label=\"b_crit\",\n", - " xscale=:log10,\n", - " #yscale=:log10,\n", - " xlabel=\"Sample Number\",\n", - " ylabel=\"b_crit\"\n", - ")\n", - "\n", - "xticks!(p1,\n", - " [5, 10, 100, 1000, 10000, 100000, 1000000],\n", - " [\"5\", \"10\", \"100\", \"1k\", \"10k\", \"100k\", \"1M\"]\n", - ")\n", - "\n", - "p2 = plot(\n", - " xlabel=\"Q\",\n", - " ylabel=\"balance\",\n", - " title=\"Torque balance vs Q\"\n", - ")\n", - "\n", - "for i in sample_number\n", - " plot!(p2, Qs_n_dict[i], bal_n_dict[i],\n", - " lw=2,\n", - " label=\"n=$i\")\n", - "end\n", - "\n", - "p3 = plot(layout=(4, 2), size=(1000, 800))\n", - "\n", - "for (k, i) in enumerate(sample_number)\n", - " plot!(\n", - " p3[k],\n", - " Qs_n_dict[i],\n", - " bal_n_dict[i],\n", - " lw=2,\n", - " label=\"n=$i\",\n", - " xlabel=\"Q\",\n", - " ylabel=\"balance\",\n", - " title=\"n = $i\"\n", - " )\n", - "end\n", - "\n", - "display(p1)\n", - "display(p2)\n", - "display(p3)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3", - "metadata": {}, - "outputs": [], - "source": [ - "println(\"bcrit = $bcrit\")" - ] - } - ], - "metadata": { - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/src/Tearing/CriticalResonantField/CRF Dev/gslayer.txt b/src/Tearing/CriticalResonantField/CRF Dev/gslayer.txt deleted file mode 100644 index 91cc2f862..000000000 --- a/src/Tearing/CriticalResonantField/CRF Dev/gslayer.txt +++ /dev/null @@ -1,466 +0,0 @@ - MODULE gslayer_mod - - USE sglobal_mod, ONLY: out_unit, r8, mu0, m_p, chag, lnLamb, - $ Q_e,Q_i,pr,pe,c_beta,ds,tau, - $ eta,visc,rho_s,lu,omega_e,omega_i, - $ delta_n,layfac, - $ Q - USE delta_mod, ONLY: riccati,riccati_out, - $ parflow_flag,PeOhmOnly_flag - - IMPLICIT NONE - -c----------------------------------------------------------------------- -c torque balance scan resolution. public so that gpout_singfld can -c size the netcdf dimension from the same source of truth. -c----------------------------------------------------------------------- - INTEGER, PARAMETER :: slayer_inum=200 - INTEGER, PARAMETER :: slayer_nref=4 -c----------------------------------------------------------------------- -c dedicated logarithmic sampling window bracketing Q_e, the electron -c diamagnetic frequency. (Q-Q_e) sits in the denominator of both G -c and C3 in delta.f, so the layer solve is singular there; the -c coarse scan steps over that neighbourhood with dQ=0.1 and the -c adaptive refinement only visits it when the torque-balance peak -c happens to land on it. These samples always resolve it, so the -c structure can be inspected on every surface rather than only on -c the ones that fell into it. -c -c PURELY DIAGNOSTIC: filled after br_th is computed, and tagged -c kpass=slayer_qetag so the threshold search cannot see them. -c Costs slayer_nqe extra lsode solves per surface (~40% on top of -c the 1005 the scan already does). -c----------------------------------------------------------------------- - INTEGER, PARAMETER :: slayer_nqe=400 - INTEGER, PARAMETER :: slayer_qetag=99 - REAL(r8), PARAMETER :: slayer_qefar=1.0e-1_r8 - REAL(r8), PARAMETER :: slayer_qenear=1.0e-9_r8 - INTEGER, PARAMETER :: slayer_nq=(slayer_inum+1)*(slayer_nref+1) - $ +slayer_nqe -c----------------------------------------------------------------------- -c every term of Cole & Fitzpatrick Eq. (61) on one rational -c surface, -c Im[Delta]/|alpha+Delta|**2 -c = 2*P*(Q0-Q)/(S*kappa_hat*(b_r/B_phi)**2) -c recorded so the balance can be rebuilt piece by piece and -c rescanned in post processing. every component is default -c initialized, so both ALLOCATE and INTENT(OUT) leave a well -c defined (zero) state even when the layer solve is skipped. -c -c kpass tags the scan pass that produced each sample: 0 for the -c coarse scan, 1..slayer_nref for the adaptive refinement passes. -c----------------------------------------------------------------------- - TYPE :: slayer_diag_type - REAL(r8), DIMENSION(slayer_nq) :: qs=0.0_r8 - REAL(r8), DIMENSION(slayer_nq) :: lhs=0.0_r8 - REAL(r8), DIMENSION(slayer_nq) :: rhs=0.0_r8 - REAL(r8), DIMENSION(slayer_nq) :: bal=0.0_r8 - REAL(r8), DIMENSION(slayer_nq) :: brb=0.0_r8 - COMPLEX(r8), DIMENSION(slayer_nq) :: dlt=(0.0_r8,0.0_r8) - INTEGER, DIMENSION(slayer_nq) :: kpass=0 - REAL(r8) :: alpha=0.0_r8, kaphat=0.0_r8, slun=0.0_r8 - REAL(r8) :: prnd=0.0_r8, q0v=0.0_r8, qcnv=0.0_r8 - REAL(r8) :: qev=0.0_r8, qiv=0.0_r8, dsv=0.0_r8 - REAL(r8) :: cbeta=0.0_r8, tratio=0.0_r8, pev=0.0_r8 - REAL(r8) :: lfac=0.0_r8, dnorm=0.0_r8, rhos=0.0_r8 - REAL(r8) :: etav=0.0_r8, viscv=0.0_r8, tauh=0.0_r8 - REAL(r8) :: taur=0.0_r8, tauv=0.0_r8, taui=0.0_r8 - REAL(r8) :: shr=0.0_r8, bl=0.0_r8, va=0.0_r8 - REAL(r8) :: rhom=0.0_r8, lbet=0.0_r8, omg=0.0_r8 - REAL(r8) :: qsol=0.0_r8, wsol=0.0_r8, brth=0.0_r8 - REAL(r8) :: mxbal=0.0_r8, qmn=0.0_r8, qmx=0.0_r8 - END TYPE slayer_diag_type - - CONTAINS - -c----------------------------------------------------------------------- -c subprogram 1. gpec_slayer. -c run slayer to provide b_crit(ising). -c----------------------------------------------------------------------- -c----------------------------------------------------------------------- -c declarations. -c----------------------------------------------------------------------- - SUBROUTINE gpec_slayer(n_e,t_e,n_i,t_i,zeff,omega,omega_e, - $ omega_i,qval,sval,bt,rs,R0,mu_i,inpr,mms,nns,ascii_flag, - $ delta,psi0,jxb,omega_sol,br_th,diag,inlayfac,inlayfrac) - - REAL(r8),INTENT(IN) :: n_e,t_e,n_i,t_i,omega,omega_e,omega_i, - $ qval,sval,bt,rs,R0,zeff,inpr - REAL(r8),INTENT(IN),OPTIONAL :: inlayfac,inlayfrac - REAL(r8) :: layfac_max,layfac_frac - INTEGER, INTENT(IN) :: mms,nns,mu_i - LOGICAL, INTENT(IN) :: ascii_flag - COMPLEX(r8),INTENT(OUT) :: delta,psi0 - REAL(r8),INTENT(OUT) :: jxb,omega_sol,br_th - TYPE(slayer_diag_type), INTENT(OUT), OPTIONAL :: diag - - INTEGER :: i,inum - INTEGER, DIMENSION(1) :: index - - REAL(r8) :: inQ,inQ_e,inQ_i,inpe,inc_beta,inds,intau,inlu - REAL(r8) :: mrs,nrs,rho,b_l,v_a,Qconv,Q0,delta_n_p, - $ lbeta,tau_i,tau_h,tau_r,tau_v - REAL(r8) :: inQ_min,inQ_max,Q_sol,maxbal - INTEGER :: ipass - INTEGER, PARAMETER :: nref=slayer_nref - REAL(r8) :: xpk,rlo,rhi,rdq,rdqc,xq,bloc,jloc - COMPLEX(r8) :: dloc - -c Eq. (61) term capture. cqs/cdlt/clhs/crhs/cbal/cbrb hold every -c sample of the coarse and refinement scans, cpass its pass tag, -c and iperm the permutation that sorts them by ascending Q. - INTEGER :: j,k,kk - INTEGER, DIMENSION(slayer_nq) :: iperm,cpass - REAL(r8), DIMENSION(slayer_nq) :: cqs,clhs,crhs,cbal,cbrb - COMPLEX(r8), DIMENSION(slayer_nq) :: cdlt - REAL(r8) :: kaphat,xtmp - - REAL(r8), DIMENSION(:), ALLOCATABLE :: inQs,iinQs,jxbl,bal - COMPLEX(r8), DIMENSION(:), ALLOCATABLE :: deltal - CHARACTER(3) :: sn,sm - - parflow_flag=.FALSE. - PeOhmOnly_flag=.TRUE. - riccati_out=.FALSE. - - mrs = real(mms,4) - nrs = real(nns,4) - - ! String representations of the m and n mode numbers - IF (nns<10) THEN - WRITE(UNIT=sn,FMT='(I1)') nns - sn=ADJUSTL(sn) - ELSE - WRITE(UNIT=sn,FMT='(I2)') nns - ENDIF - IF (mms<10) THEN - WRITE(UNIT=sm,FMT='(I1)') mms - sm=ADJUSTL(sm) - ELSEIF (mms<100) THEN - WRITE(UNIT=sm,FMT='(I2)') mms - sm=ADJUSTL(sm) - ELSE - WRITE(UNIT=sm,FMT='(I3)') mms - ENDIF - - inpe=0.0 ! Waybright added this - - tau= t_i/t_e ! ratio of ion to electron temperature - tau_i = 6.6e17*mu_i**0.5*(t_i/1e3)**1.5/(n_e*lnLamb) ! ion colls. - eta= 1.65e-9*lnLamb/(t_e/1e3)**1.5 ! spitzer resistivity (wesson) - rho=(mu_i*m_p)*n_e ! mass density - - b_l=(nrs/mrs)*rs*sval*bt/R0 ! characteristic magnetic field - v_a=b_l/(mu0*rho)**0.5 ! alfven velocity - rho_s=1.02e-4*(mu_i*t_e)**0.5/bt ! ion Lamour by elec. Temp. - - tau_h=R0*(mu0*rho)**0.5/(nns*sval*bt) ! alfven time across surface - tau_r=mu0*rs**2.0/eta ! resistive time scale - tau_v=tau_r/inpr ! rho*rs**2.0/visc ! viscous time scale - - ! this one must be anomalous. calculated back from pr. - visc= rho*rs**2.0/tau_v - - lu=tau_r/tau_h ! Lundquist number - - Qconv=lu**(1.0/3.0)*tau_h ! conversion to Qs based on Cole - - ! note Q depends on Qconv even if omega is fixed. - Q=Qconv*omega - Q_e=-Qconv*omega_e - Q_i=-Qconv*omega_i - - ! This is the most critical parameter - ds=lu**(1.0/3.0)*rho_s/rs ! conversion based on Cole. - - lbeta=(5.0/3.0)*mu0*n_e*chag*(t_e+t_i)/bt**2.0 - c_beta=(lbeta/(1.0+lbeta))**0.5 - - delta_n=lu**(1.0/3.0)/rs ! norm factor for delta primes - - inQ=Q - inQ_e=Q_e - inQ_i=Q_i - inc_beta=c_beta - inds=ds - intau=tau - Q0=Q -c----------------------------------------------------------------------- -c set the layer regularization width. -c -c riccati excises a disc of radius layfac around Q_e, where Im[Delta] -c has a zero and bal=2P(Q0-Q)/lhs therefore has a pole. Without it the -c coarse scan and its refinement walk into that pole and MAXVAL(bal) -c returns a threshold set by the scan spacing rather than by the -c saddle-node bifurcation. gpec_slayer never assigned layfac, so on -c this path the guard was dead. -c -c A fixed width is not safe on every surface: the disc [Q_e-layfac, -c Q_e+layfac] can be a large fraction of the physical branch, and on -c high-m surfaces it can swallow the turning point or Q0 itself -- -c quietly, since a number still comes back. So the width is scaled to -c the accessible branch |Q0-Q_e| and capped: -c -c layfac_frac > 0 : layfac = MIN(layfac_max, layfac_frac*|Q0-Q_e|) -c layfac_frac <= 0: layfac = layfac_max (fixed width) -c layfac_max <= 0: layfac = 0 (guard off) -c -c Exposed through gpec.in so the choice is auditable per run; it is a -c physics judgement, not a constant. -c----------------------------------------------------------------------- - layfac_max=0.02_r8 - IF (PRESENT(inlayfac)) layfac_max=inlayfac - layfac_frac=0.25_r8 - IF (PRESENT(inlayfrac)) layfac_frac=inlayfrac - IF (layfac_max>0.0_r8) THEN - IF (layfac_frac>0.0_r8) THEN - layfac=MIN(layfac_max,layfac_frac*ABS(Q0-inQ_e)) - ELSE - layfac=layfac_max - ENDIF - ELSE - layfac=0.0_r8 - ENDIF -c----------------------------------------------------------------------- -c calculate basic delta, torque, balance, error fields. -c----------------------------------------------------------------------- - delta_n_p=1e-2 - ! kappa_hat of Eq. (61) is implicit in the br_th expression at the - ! end of this routine: sqrt(maxbal/lu*(sval**2/2)) is identically - ! sqrt(maxbal/(lu*kappa_hat)) for kappa_hat=2/sval**2. Named here - ! for output only; it is never used in a physics expression, so - ! the threshold is unchanged. - IF (sval/=0.0_r8) THEN - kaphat=2.0_r8/sval**2.0 - ELSE - kaphat=0.0_r8 - ENDIF - delta=riccati(inQ,inQ_e,inQ_i,inpr,inc_beta,inds,intau,inpe) - psi0=1.0/ABS(delta+delta_n_p) ! a.u. - jxb=-AIMAG(1.0/(delta+delta_n_p)) ! a.u. -c---------------------------------------------------------------------- -c find solutions based on simple torque balance. -c----------------------------------------------------------------------- - IF (Q0>inQ_e) THEN - inQ_max=2.0*Q0 - inQ_min=1.05*inQ_e - ELSE - inQ_max=0.95*inQ_e - IF (Q0>0) THEN - inQ_min=0.8*inQ_i - ELSE - inQ_min=1.5*MINVAL((/Q0,inQ_i/)) - ENDIF - ENDIF - - ! Scan of rotation - inQ_max=10.0 - inQ_min=-10.0 - inum=slayer_inum - ALLOCATE(inQs(0:inum),deltal(0:inum),jxbl(0:inum),bal(0:inum)) - DO i=0,inum - inQs(i)=inQ_min+(REAL(i)/inum)*(inQ_max-inQ_min) - deltal(i)=riccati(inQs(i),inQ_e,inQ_i, - $ inpr,inc_beta,inds,intau,inpe) - jxbl(i)=-AIMAG(1.0/(deltal(i)+delta_n_p)) - bal(i)=2.0*inpr*(Q0-inQs(i))/jxbl(i) - ENDDO - - ! Capture the coarse pass (tag 0). This only reads inQs/deltal/ - ! jxbl/bal, so both the ascii dump and the refinement below are - ! bit for bit unchanged. The Eq. (61) right hand side numerator - ! is recomputed rather than harvested out of the bal expression - ! above; 2.0*inpr*(Q0-inQs(i)) is a pure product chain, so the - ! recomputed value is identical to the one formed inline. - DO i=0,inum - cqs(i+1)=inQs(i) - cdlt(i+1)=deltal(i) - clhs(i+1)=jxbl(i) - crhs(i+1)=2.0*inpr*(Q0-inQs(i)) - cbal(i+1)=bal(i) - cpass(i+1)=0 - ENDDO - - ! Write torque balance curves to file for diagnostic purposes - IF(ascii_flag)THEN - OPEN(UNIT=out_unit,FILE="gpec_slayer_torque_balance_m"// - $ TRIM(sm)//"_n"//TRIM(sn)//".out", - $ STATUS="UNKNOWN") - WRITE(out_unit,'(1x,5(a17))') "inQ","RE(delta)", - $ "IM(delta)","jxb","bal" - DO i=0,inum - WRITE(out_unit,'(1x,5(es17.8e3))') - $ inQs(i),REAL(deltal(i)),AIMAG(deltal(i)),jxbl(i),bal(i) - ENDDO - CLOSE(out_unit) - ENDIF - - ! The coarse scan above gives the overall torque-balance shape - ! and the diagnostic output. The locking "nose" (the maximum of - ! bal) can be a very narrow spike near inQ=Q0, however, and the - ! coarse grid can step right over it, leaving a spuriously - ! negative MAXVAL(bal) and hence a NaN br_th. Bracket the coarse - ! maximum and iteratively refine the scan around the running peak - ! so the nose is resolved regardless of how narrow it is. Exclude - ! non-finite entries (NaN from 0/0, Inf from a near-zero jxbl). - index=MAXLOC(bal,MASK=(bal==bal .AND. ABS(bal)maxbal) THEN - maxbal=bloc - xpk=xq - ENDIF - ENDDO - rlo=xpk-2.0*rdq - rhi=xpk+2.0*rdq - ENDDO - Q_sol=xpk - omega_sol=xpk/Qconv - ! If even the refined nose is non-positive the surface has no - ! finite penetration threshold; floor at zero and warn rather - ! than propagating a NaN into b_crit/Phi_res_crit downstream. - IF (maxbal>0.0_r8) THEN - br_th=sqrt(maxbal/lu*(sval**2.0/2.0)) - ELSE - br_th=0.0_r8 - WRITE(*,'(1x,a,i0,a,i0,a)') - $ "!! WARNING: SLAYER torque balance has no positive "// - $ "maximum at m=",mms,", n=",nns,"; br_th set to 0" - ENDIF -c----------------------------------------------------------------------- -c assemble the Eq. (61) record: b_r/B_phi implied by each balance -c point, then merge the coarse and refined samples onto one -c ascending Q grid so the narrow nose is densely resolved and the -c curve can be interpolated in post processing. -c----------------------------------------------------------------------- - ! Dedicated logarithmic sweep through the Q_e singularity, half - ! the samples on each side, |Q-Q_e| running from slayer_qefar in - ! to slayer_qenear. br_th is already fixed above and these are - ! tagged slayer_qetag, so they are invisible to the peak search. - DO i=1,slayer_nqe/2 - xq=slayer_qefar*(slayer_qenear/slayer_qefar) - $ **(REAL(i-1,r8)/REAL(slayer_nqe/2-1,r8)) - DO j=0,1 - k=(inum+1)*(nref+1)+(i-1)*2+j+1 - IF (j==0) THEN - cqs(k)=inQ_e-xq - ELSE - cqs(k)=inQ_e+xq - ENDIF - cdlt(k)=riccati(cqs(k),inQ_e,inQ_i,inpr, - $ inc_beta,inds,intau,inpe) - clhs(k)=-AIMAG(1.0/(cdlt(k)+delta_n_p)) - crhs(k)=2.0*inpr*(Q0-cqs(k)) - cbal(k)=crhs(k)/clhs(k) - cpass(k)=slayer_qetag - ENDDO - ENDDO - ! deliberately the same expression form as br_th above, so the - ! peak sample reproduces br_th exactly rather than differing in - ! the last bit. - DO k=1,slayer_nq - IF (cbal(k)==cbal(k) .AND. cbal(k)>0.0_r8 - $ .AND. ABS(cbal(k))=1) - IF (cqs(iperm(j))<=xtmp) EXIT - iperm(j+1)=iperm(j) - j=j-1 - ENDDO - iperm(j+1)=kk - ENDDO - IF (PRESENT(diag)) THEN - DO k=1,slayer_nq - kk=iperm(k) - diag%qs(k)=cqs(kk) - diag%dlt(k)=cdlt(kk) - diag%lhs(k)=clhs(kk) - diag%rhs(k)=crhs(kk) - diag%bal(k)=cbal(kk) - diag%brb(k)=cbrb(kk) - diag%kpass(k)=cpass(kk) - ENDDO - ! scalars are taken from the local copies, never from the - ! sglobal_mod globals Q/Q_e/Q_i/ds/tau/c_beta/pr/pe: riccati - ! overwrites those on every call, so by this point the module - ! Q holds the last refinement sample rather than Q0. - diag%alpha=delta_n_p - diag%kaphat=kaphat - diag%slun=lu - diag%prnd=inpr - diag%q0v=Q0 - diag%qcnv=Qconv - diag%qev=inQ_e - diag%qiv=inQ_i - diag%dsv=inds - diag%cbeta=inc_beta - diag%tratio=intau - diag%pev=inpe - diag%lfac=layfac - diag%dnorm=delta_n - diag%rhos=rho_s - diag%etav=eta - diag%viscv=visc - diag%tauh=tau_h - diag%taur=tau_r - diag%tauv=tau_v - diag%taui=tau_i - diag%shr=sval - diag%bl=b_l - diag%va=v_a - diag%rhom=rho - diag%lbet=lbeta - diag%omg=omega - diag%qsol=Q_sol - diag%wsol=omega_sol - diag%brth=br_th - diag%qmn=inQ_min - diag%qmx=inQ_max - IF (maxbal>-HUGE(maxbal)) THEN - diag%mxbal=maxbal - ELSE - diag%mxbal=0.0_r8 - ENDIF - ENDIF - DEALLOCATE(inQs,deltal,jxbl,bal) - - RETURN - END SUBROUTINE gpec_slayer - - END MODULE gslayer_mod diff --git a/src/Tearing/CriticalResonantField/CRF Dev/pole_testing.ipynb b/src/Tearing/CriticalResonantField/CRF Dev/pole_testing.ipynb deleted file mode 100644 index d7f16a2b4..000000000 --- a/src/Tearing/CriticalResonantField/CRF Dev/pole_testing.ipynb +++ /dev/null @@ -1,395 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "0", - "metadata": {}, - "outputs": [], - "source": [ - "using Pkg\n", - "Pkg.activate(\"/Users/bursche/Documents/GitHub/JPEC_BCRIT\")\n", - "Base.active_project()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1", - "metadata": {}, - "outputs": [], - "source": [ - "using GeneralizedPerturbedEquilibrium\n", - "using GeneralizedPerturbedEquilibrium: Analysis\n", - "using GeneralizedPerturbedEquilibrium: InnerLayer\n", - "using GeneralizedPerturbedEquilibrium.InnerLayer: solve_inner\n", - "using GeneralizedPerturbedEquilibrium: Tearing\n", - "using ..InnerLayer\n", - "using ..InnerLayer: InnerLayerModel, solve_inner, GGJModel, GGJParameters,\n", - " SLAYERModel, SLAYERParameters\n", - "\n", - "using Plots\n", - "using Printf\n", - "default(\n", - " fontfamily=\"Georgia\",\n", - " margin=12Plots.mm,\n", - " size=(800, 500),\n", - " dpi=150\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2", - "metadata": {}, - "outputs": [], - "source": [ - "struct TorqueBalance{M<:InnerLayerModel,P}\n", - " model::M\n", - " params::P\n", - " Q0::Float64\n", - " P::Float64\n", - " lu::Float64\n", - " sval::Float64\n", - "end\n", - "\n", - "function torque_balance_value(tb::TorqueBalance, Q::Number)\n", - " Δ = solve_inner(tb.model, tb.params, ComplexF64(Q)).tearing\n", - " alpha = 1e-2\n", - " jxb = -imag(1.0 / (Δ + alpha))\n", - " return 2.0 * tb.P * (tb.Q0 - Q) / jxb, Δ\n", - "end\n", - "\n", - "function torque_balance_scan(tb; Qmin=-10.0, Qmax=10.0, n=20000)\n", - " Qs = range(Qmin, Qmax; length=n)\n", - " torque_out = [torque_balance_value(tb, q) for q in Qs]\n", - " bal = [x[1] for x in torque_out]\n", - " Δs = [x[2] for x in torque_out]\n", - " positive = isfinite.(bal) .& (bal .> 0.0)\n", - "\n", - " if !any(positive)\n", - " @warn \"No positive torque balance found in the specified range. Try increasing the number of Q samples scanned or adjusting the range.\"\n", - " return Qs, bal, NaN, NaN, NaN, Δs\n", - " end\n", - "\n", - " # Find the highest point, then remove candidates within ΔQ of it.\n", - "\n", - " idx_maxima = findall(isfinite.(bal) .& (bal .> 0))\n", - " sort!(idx_maxima, by=i -> bal[i], rev=true)\n", - " selected = Int[]\n", - " min_ΔQ = 0.001 * abs(Qmax - Qmin)\n", - "\n", - " for i in idx_maxima\n", - " if all(abs(Qs[i] - Qs[j]) > min_ΔQ for j in selected)\n", - " push!(selected, i)\n", - " end\n", - " length(selected) == 2 && break\n", - " end\n", - "\n", - " if isempty(selected)\n", - " @warn \"No usable positive torque-balance maximum found. Try increasing the number of Q samples scanned or adjusting the range.\"\n", - " return Qs, bal, NaN, NaN, NaN, Δs\n", - " end\n", - "\n", - " idx_maxima = selected\n", - "\n", - "\n", - " # Find all local maxima in the positive region\n", - " #idx_positive = findall(positive)\n", - " #idx_maxima = idx_positive[partialsortperm(bal[idx_positive], 1:min(2, length(idx_positive)); rev=true)]\n", - " maxima = bal[idx_maxima]\n", - " Qs_maxima = Qs[idx_maxima]\n", - " # find index, q val and bal val of the q closest to Q_e\n", - " idx_closest_Q_e = argmin(abs.(Qs .+ tb.params.Q_e)) # + Q_e since Q_e = -omega_e * Qconv\n", - " q_closest_Q_e = Qs[idx_closest_Q_e]\n", - " bal_closest_Q_e = bal[idx_closest_Q_e]\n", - "\n", - " # find index, q val and bal val of the q closest to Q_i\n", - " idx_closest_Q_i = argmin(abs.(Qs .+ tb.params.Q_i)) # + Q_i since Q_i = -omega_i * Qconv\n", - " q_closest_Q_i = Qs[idx_closest_Q_i]\n", - " bal_closest_Q_i = bal[idx_closest_Q_i]\n", - " \n", - " println(\"Local maxima indices: \", idx_maxima, \" with values: \", maxima, \" and corresponding Qs: \", Qs_maxima, \" closest Q to Q_e: \", q_closest_Q_e, \" closest Q to Q_i: \", q_closest_Q_i)\n", - " # check if 1st q_maxima is same as Q_e or Q_i from p\n", - " if idx_maxima[1] == idx_closest_Q_e || idx_maxima[1] == idx_closest_Q_i\n", - " if length(idx_maxima) < 2\n", - " @warn \"The first local maximum corresponds to a pole from Q_e or Q_i, but there is no second local maximum to select. Try increasing the number of Q samples scanned or adjusting the range.\"\n", - " return Qs, bal, NaN, NaN, NaN, Δs\n", - " end\n", - " println(\"Warning: The first local maximum may correspond to an electron or ion diamagnetic resonance. Selecting the second local maximum instead.\")\n", - " if idx_maxima[2] == idx_closest_Q_e || idx_maxima[2] == idx_closest_Q_i\n", - " @warn \"Both the first and second local maxima correspond to poles from Q_e or Q_i. Unable to select a valid local maximum. Try increasing the number of Q samples scanned or adjusting the range.\"\n", - " return Qs, bal, NaN, NaN, NaN, Δs\n", - " end\n", - " idx_maximum = idx_maxima[2]\n", - " maximum = bal[idx_maximum]\n", - " Qmaximum = Qs[idx_maximum]\n", - " else\n", - " idx_maximum = idx_maxima[1]\n", - " maximum = bal[idx_maximum]\n", - " Qmaximum = Qs[idx_maximum]\n", - " end\n", - "\n", - " println(\"Selected local maximum index: \", idx_maximum, \" with value: \", maximum, \" and corresponding Q: \", Qmaximum)\n", - "\n", - " br_crit = sqrt(maximum / tb.lu * (tb.sval^2 / 2.0))\n", - "\n", - " return Qs, bal, Qmaximum, br_crit, idx_maximum, Δs\n", - "end" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3", - "metadata": {}, - "outputs": [], - "source": [ - "p = GeneralizedPerturbedEquilibrium.InnerLayer.slayer_parameters(\n", - " n_e=1e19, t_e=1e3, t_i=1e3,\n", - " omega=0.0, omega_e=40, omega_i=-20,\n", - " qval=2.0, sval_r=0.5, bt=2.0, rs=1.0, R0=3.0, mu_i=2.0, zeff=1.0,\n", - " chi_perp=1.0, chi_tor=1.0, m=2, n=1\n", - ")\n", - "p = GeneralizedPerturbedEquilibrium.InnerLayer.SLAYERParameters(\n", - " ising=p.ising,\n", - " m=p.m, n=p.n,\n", - " tau=p.tau, lu=p.lu, c_beta=p.c_beta, D_norm=p.D_norm,\n", - " P_perp=p.P_perp, P_tor=p.P_tor,\n", - " Q_e=2, Q_i=3, iota_e=p.iota_e,\n", - " tauk=p.tauk, tau_r=p.tau_r, delta_n=p.delta_n,\n", - " rs=p.rs, R0=p.R0, bt=p.bt, sval_r=p.sval_r,\n", - " dr_val=p.dr_val, dgeo_val=p.dgeo_val,\n", - " eta=p.eta, d_beta=p.d_beta,\n", - " dc_tmp=p.dc_tmp, dc_type=p.dc_type\n", - ")\n", - "\n", - "tb = TorqueBalance(\n", - " GeneralizedPerturbedEquilibrium.InnerLayer.SLAYERModel(;),\n", - " p,\n", - " 0.5,\n", - " 61.0, #1.0\n", - " p.lu,\n", - " p.sval_r\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4", - "metadata": {}, - "outputs": [], - "source": [ - "Qs, bal, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb,Qmin=-2.5, Qmax=0, n=200000)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5", - "metadata": {}, - "outputs": [], - "source": [ - "Qmax = 10\n", - "Qmin = -10\n", - "positive = isfinite.(bal) .& (bal .> 0.0)\n", - "\n", - "if !any(positive)\n", - " @warn \"No positive torque balance found in the specified range. Try increasing the number of Q samples scanned or adjusting the range.\"\n", - " return Qs, bal, NaN, NaN, NaN, Δs\n", - "end\n", - "\n", - "# Find the highest point, then remove candidates within ΔQ of it.\n", - "\n", - "idx_maxima = findall(isfinite.(bal) .& (bal .> 0))\n", - "sort!(idx_maxima, by=i -> bal[i], rev=true)\n", - "selected = Int[]\n", - "min_ΔQ = 0.001 * abs(Qmax - Qmin)\n", - "\n", - "for i in idx_maxima\n", - " if all(abs(Qs[i] - Qs[j]) > min_ΔQ for j in selected)\n", - " push!(selected, i)\n", - " end\n", - " length(selected) == 2 && break\n", - "end\n", - "\n", - "if isempty(selected)\n", - " @warn \"No usable positive torque-balance maximum found. Try increasing the number of Q samples scanned or adjusting the range.\"\n", - " return Qs, bal, NaN, NaN, NaN, Δs\n", - "end\n", - "\n", - "idx_maxima = selected\n", - "\n", - "\n", - "# Find all local maxima in the positive region\n", - "#idx_positive = findall(positive)\n", - "#idx_maxima = idx_positive[partialsortperm(bal[idx_positive], 1:min(2, length(idx_positive)); rev=true)]\n", - "maxima = bal[idx_maxima]\n", - "Qs_maxima = Qs[idx_maxima]\n", - "# find index, q val and bal val of the q closest to Q_e\n", - "idx_closest_Q_e = argmin(abs.(Qs .+ tb.params.Q_e)) # + Q_e since Q_e = -omega_e * Qconv\n", - "q_closest_Q_e = Qs[idx_closest_Q_e]\n", - "bal_closest_Q_e = bal[idx_closest_Q_e]\n", - "\n", - "# find index, q val and bal val of the q closest to Q_i\n", - "idx_closest_Q_i = argmin(abs.(Qs .+ tb.params.Q_i)) # + Q_i since Q_i = -omega_i * Qconv\n", - "q_closest_Q_i = Qs[idx_closest_Q_i]\n", - "bal_closest_Q_i = bal[idx_closest_Q_i]\n", - "\n", - "println(\"Local maxima indices: \", idx_maxima, \" with values: \", maxima, \" and corresponding Qs: \", Qs_maxima, \" closest Q to Q_e: \", q_closest_Q_e, \" closest Q to Q_i: \", q_closest_Q_i)\n", - "# check if 1st q_maxima is same as Q_e or Q_i from p\n", - "if idx_maxima[1] == idx_closest_Q_e || idx_maxima[1] == idx_closest_Q_i\n", - " if length(idx_maxima) < 2\n", - " @warn \"The first local maximum corresponds to a pole from Q_e or Q_i, but there is no second local maximum to select. Try increasing the number of Q samples scanned or adjusting the range.\"\n", - " return Qs, bal, NaN, NaN, NaN, Δs\n", - " end\n", - " println(\"Warning: The first local maximum may correspond to an electron or ion diamagnetic resonance. Selecting the second local maximum instead.\")\n", - " if idx_maxima[2] == idx_closest_Q_e || idx_maxima[2] == idx_closest_Q_i\n", - " @warn \"Both the first and second local maxima correspond to poles from Q_e or Q_i. Unable to select a valid local maximum. Try increasing the number of Q samples scanned or adjusting the range.\"\n", - " return Qs, bal, NaN, NaN, NaN, Δs\n", - " end\n", - " idx_maximum = idx_maxima[2]\n", - " maximum = bal[idx_maximum]\n", - " Qmaximum = Qs[idx_maximum]\n", - "else\n", - " idx_maximum = idx_maxima[1]\n", - " maximum = bal[idx_maximum]\n", - " Qmaximum = Qs[idx_maximum]\n", - "end\n", - "\n", - "println(\"Selected local maximum index: \", idx_maximum, \" with value: \", maximum, \" and corresponding Q: \", Qmaximum)\n", - "\n", - "br_crit = sqrt(maximum / tb.lu * (tb.sval^2 / 2.0))\n", - "\n", - "println(Qmaximum, br_crit, idx_maximum)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6", - "metadata": {}, - "outputs": [], - "source": [ - "jxbs = [-imag(1.0 / (d + 1e-2)) for d in Δs]\n", - "T_VISC = [2.0 * tb.P * (tb.Q0 - q) for q in Qs] #(q, jxb) in zip(Qs, jxbs)]\n", - "#br_t = brcrit\n", - "#println(tb.lu, \" \", tb.sval, \" \", br_t, \" \", p.bt, \" \", 1e-2)\n", - "#@printf(\"br_crit = %.5e\\n\", brcrit)\n", - "#T_EM = tb.lu * tb.sval^2/2 * (brcrit)^2 * jxbs\n", - "T_EM = -imag(1.0 ./ (Δs .+ 1e-2)) *brcrit^2*tb.lu/(tb.sval^2/2)\n", - "i = Qpeak_ind\n", - "println(T_VISC[i]/(tb.lu * tb.sval^2/2 * (brcrit)^2 * jxbs[i]))\n", - "println(T_VISC[i] / (tb.lu * tb.sval^2/2 * (brcrit * p.bt)^2 * jxbs[i]))\n", - "println(T_VISC[i] / ( (brcrit / p.bt)^2 * jxbs[i]))\n", - "\n", - "#T_EM ∝ S ξ̂ (br/Bφ)² Im[-Δ̂(Q)⁻¹]\n", - "#T_visc ∝ 2 P (Q0 − Q)\n", - "\n", - "xmi = -2.5\n", - "xma = 0\n", - "\n", - "\"\"\"\n", - "p1 = plot(Qs, imag.(Δs), label=\"Im(Δ)\", lw=2, xlim=(xmi, xma))\n", - "#plot!(p1, Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", - "xlabel!(p1, \"Q\")\n", - "ylabel!(p1, \"Δ\")\n", - "#title!(p1, \"Inner-layer Δ(Q)\")\n", - "\"\"\"\n", - "\n", - "p1 = plot( Qs, T_VISC, label=\"T_V\", lw=2, xlim=(xmi, xma))#,ylim=(-1000,1000))\n", - "plot!(p1, Qs, T_EM, label=\"T_EM\", lw=2)\n", - "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - "xlabel!(p1, \"Q\")\n", - "ylabel!(p1, \"Torque\")\n", - "\n", - "#p2 = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", - "p2 = plot( Qs, T_VISC, label=\"T_V\", lw=2, xlim=(xmi, xma))#,ylim=(0,500))\n", - "plot!(p2, Qs, T_EM, label=\"T_EM\", lw=2)\n", - "vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - "xlabel!(p2, \"Q\")\n", - "ylabel!(p2, \"Torque\")\n", - "#title!(p2, \"jxb(Q) = -Im[1/(Δ + δ_n_p)]\")\n", - "\n", - "p3 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2, xlim=(xmi, xma)) #xlim=(-1.3,-.8),ylim=(375,389))#\n", - "plot!(p3, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", - "loc_max_ind= [4001, 10050, 10094, 10186, 10195, 10213, 10258, 10272, 10340, 10355, 10365, 10376, 10385, 10387, 10392, 10405, 10412, 10421, 10430, 10443, 10450, 10457, 10470, 10473, 10494, 10498, 10512, 10520, 10537, 10544, 10552, 10557, 10573, 10576, 10578, 10586, 10588, 10596, 10606, 10610, 10632, 10637, 10648, 10655, 10659, 10665, 10670, 10676, 10679, 10691, 10695, 10697, 10705, 10707, 10719, 10730, 10742, 10746, 10751, 10755, 10761, 10765, 10770, 10776, 10778, 10783, 10786, 10788, 10793, 10798, 10810, 10814, 10821, 10824, 10829, 10834, 10837, 10841, 10843, 10847, 10849, 10856, 10858, 10861, 10863, 10868, 10871, 10877, 10881, 10887, 10892, 10895, 10897, 10900, 10904, 10906, 10909, 10911, 10916, 10918, 10923, 10929, 10931, 10933, 10937, 10942, 10945, 10950, 10955, 10959, 10963, 10969, 10971, 10974, 10976, 10981, 10984, 10988, 10991, 10994, 10997, 11001, 11003, 11005, 11012, 11015, 11018, 11021, 11024, 11027, 11029, 11031, 11033, 11036, 11039, 11042, 11044, 11048, 11053, 11056, 11058, 11060, 11062, 11064, 11068, 11078, 11080, 11083, 11085, 11096, 11098, 11100, 11102, 11104, 11106, 11109, 11111, 11116, 11119, 11121, 11128, 11131, 11133, 11139, 11145, 11148, 11150, 11152, 11155, 11157, 11162, 11165, 11169, 11174, 11180, 11183, 11186, 11188, 11205, 11218, 11220, 11222, 11224, 11228, 11233, 11235, 11243, 11249, 11254, 11257, 11259, 11276, 11281, 11294, 11299, 11303, 11306, 11312, 11316, 11319, 11322, 11335, 11341, 11358, 11369, 11376, 11381, 11386, 11391, 11394, 11396, 11399, 11406, 11410, 11417, 11420, 11422, 11428, 11437, 11446, 11448, 11453, 11457, 11469, 11473, 11486, 11497, 11513, 11540, 11542, 11544, 11552, 11554, 11565, 11570, 11573, 11578, 11587, 11594, 11597, 11602, 11614, 11620, 11633, 11654, 11660, 11662, 11669, 11677, 11682, 11687, 11711, 11764, 11804, 11806, 11821, 11848, 11860, 11882, 11901, 11928, 11991, 12108]\n", - "#plot!(p3, Qs[loc_max_ind], bal[loc_max_ind], seriestype=:scatter, label=\"Local Maxima\", color=:red)\n", - "loc_mx2 = [4001, 10963, 10955, 10950, 11005]\n", - "#plot!(p3, Qs[loc_mx2], bal[loc_mx2], seriestype=:scatter, label=\"Local Maxima 2\", color=:green)\n", - "ylabel!(p3, \"Torque Balance\")\n", - "#title!(p3, \"2P(Q0-Q)/jxb\")\n", - "xlabel!(p3, \"Q\")\n", - "vline!([Qpeak], label=\"Max Balance\", linestyle=:dash)\n", - "\n", - "# find index, q val and bal val of the q closest to Q_e\n", - "println(\"Q_e: \", -tb.params.Q_e)\n", - "idx_closest_Q_e = argmin(abs.(Qs .+ tb.params.Q_e))\n", - "q_closest_Q_e = Qs[idx_closest_Q_e]\n", - "bal_closest_Q_e = bal[idx_closest_Q_e]\n", - "println(\"Closest Q to Q_e: \", q_closest_Q_e, \" with balance value: \", bal_closest_Q_e, \" at index: \", idx_closest_Q_e)\n", - "println(\"B crit: \", brcrit)\n", - "vline!([-tb.params.Q_e], label=\"Q_e\", linestyle=:dashdot, color=:orange)\n", - "vline!([q_closest_Q_e], label=\"Closest Q to Q_e\", linestyle=:dashdot, color=:purple)\n", - "\n", - "#plot(p1, p2, p3, layout=(3,1), size=(800, 1000))\n", - "plot(p3, layout=(1,1), size=(800, 1000))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8", - "metadata": {}, - "outputs": [], - "source": [ - "# compare Q_e to Q of max(bal)\n", - "println(\"-Q_e = \", -p.Q_e, \" Q_i = \", p.Q_i, \" Q_peak = \", Qpeak, \" br_crit = \", brcrit)\n", - "# check if |Qpeak+Q_e| < 1e-2\n", - "println(\"|Qpeak + Q_e| = \", abs(Qpeak + p.Q_e))\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9", - "metadata": {}, - "outputs": [], - "source": [ - "# Check torque is balanced\n", - "\n", - "viscous_torque = 2*tb.P*(tb.Q0 - Qpeak)\n", - "electromagnetic_torque = -imag(1.0 / (Δs[Qpeak_ind] + 1e-2)) *brcrit^2*tb.lu/(tb.sval^2/2)\n", - "\n", - "# delta_n_p = 1e-2\n", - "# jxb = -imag(1.0 / (Δ + delta_n_p))\n", - "# bal = 2.0 * tb.P * (tb.Q0 - Q) / jxb\n", - "# br_crit = sqrt(maxbal / tb.lu * (tb.sval^2 / 2.0))\n", - "\n", - "@printf(\"br_crit = %.5e\\n\", brcrit)\n", - "@printf(\"viscous_torque = %.5e\\n\", viscous_torque)\n", - "@printf(\"electromagnetic_torque = %.5e\\n\", electromagnetic_torque)\n", - "@printf(\"ratio = %.10f\\n\", viscous_torque / electromagnetic_torque)" - ] - } - ], - "metadata": { - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/src/Tearing/CriticalResonantField/CRF Dev/sample_number.jls b/src/Tearing/CriticalResonantField/CRF Dev/sample_number.jls deleted file mode 100644 index c320ccaa9d62b84e8037da421fd24ccf2da49346..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68 ucmXr_@{wa Date: Thu, 20 Aug 2026 14:23:27 -0400 Subject: [PATCH 8/9] Cleaned up notebooks/ignore --- .gitignore | 1 - .../slayer_ex.ipynb | 257 +----------------- 2 files changed, 11 insertions(+), 247 deletions(-) diff --git a/.gitignore b/.gitignore index 8f463f94f..99ce15eb1 100644 --- a/.gitignore +++ b/.gitignore @@ -38,5 +38,4 @@ scratch/ # Local profiling scratch (one-off study scripts, not part of the package) profiling/ -examples/b_crit_standalone_example/ src/Tearing/CriticalResonantField/CRF Dev/ diff --git a/examples/DIIID-like_SLAYER_and_bcrit_example/slayer_ex.ipynb b/examples/DIIID-like_SLAYER_and_bcrit_example/slayer_ex.ipynb index ed88780dd..4e59b802d 100644 --- a/examples/DIIID-like_SLAYER_and_bcrit_example/slayer_ex.ipynb +++ b/examples/DIIID-like_SLAYER_and_bcrit_example/slayer_ex.ipynb @@ -6,17 +6,6 @@ "id": "0", "metadata": {}, "outputs": [], - "source": [ - "using Pkg\n", - "Pkg.build(\"GeneralizedPerturbedEquilibrium\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1", - "metadata": {}, - "outputs": [], "source": [ "using Pkg\n", "Pkg.activate(\"/Users/bursche/Documents/GitHub/JPEC_BCRIT\")\n", @@ -38,74 +27,17 @@ { "cell_type": "code", "execution_count": null, - "id": "2", - "metadata": {}, - "outputs": [], - "source": [ - "h5path = \"/Users/bursche/Documents/GitHub/JPEC_BCRIT/examples/DIIID-like_SLAYER_and_bcrit_example/gpec.h5\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3", - "metadata": {}, - "outputs": [], - "source": [ - "using HDF5\n", - "\n", - "h5open(h5path, \"r\") do file\n", - " println(\"Top-level keys:\")\n", - " println(collect(keys(file)))\n", - "\n", - " if haskey(file, \"Tearing\")\n", - " println(\"\\nKeys in Tearing:\")\n", - " println(collect(keys(file[\"Tearing\"])))\n", - "\n", - " if haskey(file[\"Tearing\"], \"CriticalResonantField\")\n", - " println(\"\\nKeys in Tearing/CriticalResonantField:\")\n", - " println(collect(keys(file[\"Tearing\"][\"CriticalResonantField\"])))\n", - " end\n", - " else\n", - " println(\"No Tearing group found.\")\n", - " end\n", - "end" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4", + "id": "1", "metadata": {}, "outputs": [], "source": [ - "# Print the contents of the Tearing/CriticalResonantField group\n", - "h5open(h5path, \"r\") do file\n", - " if haskey(file, \"Tearing\") && haskey(file[\"Tearing\"], \"CriticalResonantField\")\n", - " println(\"\\nContents of Tearing/CriticalResonantField:\")\n", - " # Iterate over the keys in the Tearing/CriticalResonantField group and print their names and types\n", - " for key in keys(file[\"Tearing\"][\"CriticalResonantField\"])\n", - " dataset = file[\"Tearing\"][\"CriticalResonantField\"][key]\n", - " println(\"Key: $key, Type: $(typeof(dataset))\")\n", - " # print data \n", - " if isa(dataset, HDF5.Dataset)\n", - " data = read(dataset)\n", - " println(\"Data: $data\")\n", - " end\n", - " end\n", - " else\n", - " println(\"No Tearing/CriticalResonantField group found.\")\n", - " end\n", - " # Print bcrit data as .2e (in one line)\n", - " println(\"\\nBcrit data: $(join([@sprintf(\"%.2e\", x) for x in read(file[\"Tearing\"][\"CriticalResonantField\"][\"br_crit\"])], \" \"))\")\n", - "end\n", - "\n" + "h5path = \"gpec.h5\"" ] }, { "cell_type": "code", "execution_count": null, - "id": "5", + "id": "2", "metadata": {}, "outputs": [], "source": [ @@ -115,22 +47,14 @@ { "cell_type": "code", "execution_count": null, - "id": "6", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7", + "id": "3", "metadata": {}, "outputs": [], "source": [ "function bcrit_diag_plots(Δs, Qs, bal, name)\n", "\n", " p1 = plot(Qs, imag.(Δs), label=\"Im(Δ)\", lw=2)\n", - " #plot!(p1, Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", + " plot!(p1, Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", " xlabel!(p1, \"Q\")\n", " ylabel!(p1, \"Δ\")\n", " title!(p1, \"Inner-layer Δ(Q) - $name\")\n", @@ -143,7 +67,6 @@ "\n", " plot(p1, p2, layout=(2,1), size=(500, 700))\n", "\n", - "\n", "end\n", "\n", "function plot_all_vs_rational_q(h5path)\n", @@ -172,184 +95,28 @@ " display(fig)\n", " #return fig\n", " end\n", - "end\n", - "\n", - "plot_all_vs_rational_q(h5path)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8", - "metadata": {}, - "outputs": [], - "source": [ - "using GeneralizedPerturbedEquilibrium\n", - "using GeneralizedPerturbedEquilibrium: Analysis\n", - "using GeneralizedPerturbedEquilibrium.InnerLayer: InnerLayerModel, solve_inner, GGJModel, GGJParameters,\n", - " SLAYERModel, SLAYERParameters, slayer_parameters\n", - "using GeneralizedPerturbedEquilibrium.Tearing.CriticalResonantField: TorqueBalance, torque_balance_value, torque_balance_scan\n", - "\n", - "surface_num = 5\n", - "h5open(h5path, \"r\") do file\n", - " sval_r = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"sval\"])\n", - " Q0 = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"Q0\"])\n", - " m = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"m\"])\n", - " n = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"n\"])\n", - " qval = m/n\n", - " Q_e = read(file[\"Tearing\"][\"PerSurface\"][\"Q_e\"])[surface_num]\n", - " Q_i = read(file[\"Tearing\"][\"PerSurface\"][\"Q_i\"])[surface_num]\n", - " lu = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"lu\"])\n", - " rs = read(file[\"Tearing\"][\"PerSurface\"][\"rs\"])[surface_num]\n", - " P = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"P\"])\n", - "\n", - " p = slayer_parameters( # Call slayer_parameters function to instantiate slab parameters\n", - " n_e=1e19, t_e=1e3, t_i=1e3,\n", - " omega=0.0, omega_e=40, omega_i=-20,\n", - " qval=qval, sval_r=sval_r, bt=2.0, rs=rs, R0=3.0, mu_i=2.0, zeff=1.0,\n", - " chi_perp=1.0, chi_tor=1.0, m=2, n=1\n", - " )\n", - " p = SLAYERParameters( # Modify the created SLAYERParameters struct to modify electron and ion diamagnetic resonance frequencies\n", - " ising=p.ising,\n", - " m=p.m, n=p.n,\n", - " tau=p.tau, lu=p.lu, c_beta=p.c_beta, D_norm=p.D_norm,\n", - " P_perp=p.P_perp, P_tor=p.P_tor,\n", - " Q_e=Q_e, Q_i=Q_i, iota_e=p.iota_e,\n", - " tauk=p.tauk, tau_r=p.tau_r, delta_n=p.delta_n,\n", - " rs=p.rs, R0=p.R0, bt=p.bt, sval_r=p.sval_r,\n", - " dr_val=p.dr_val, dgeo_val=p.dgeo_val,\n", - " eta=p.eta, d_beta=p.d_beta,\n", - " dc_tmp=p.dc_tmp, dc_type=p.dc_type\n", - " )\n", - "\n", - " tb = TorqueBalance( # Generate a TorqueBalance struct using the default (Fitzpatrick) SLAYERModel and the modified SLAYERParameters\n", - " SLAYERModel(;),\n", - " p, # Slayer Parameters struct\n", - " Q0, # Normalized rotation Q\n", - " P, # Magnetic Prandtl number\n", - " p.lu, # Lundquist Number\n", - " p.sval_r # r-based magnetic shear\n", - " )\n", - " Qmin = -.2\n", - " Qmax = .2\n", - " Qs, bal, Qpeak, brcrit, Qpeak_ind, Δs = torque_balance_scan(tb,Qmin=Qmin, Qmax=Qmax, n=1000) # Run actual torque balance scan, finds inner-layer delta across Q vals\n", - "\n", - "\n", - " jxbs = [-imag(1.0 / (d + 1e-2)) for d in Δs]\n", - " T_VISC = [2.0 * tb.P * (tb.Q0 - q) for q in Qs] #(q, jxb) in zip(Qs, jxbs)]\n", - " T_EM = -imag(1.0 ./ (Δs .+ 1e-2)) *brcrit^2*tb.lu/(tb.sval^2/2)\n", - " i = Qpeak_ind\n", - " println(T_VISC[i]/(tb.lu * tb.sval^2/2 * (brcrit)^2 * jxbs[i]))\n", - " println(T_VISC[i] / (tb.lu * tb.sval^2/2 * (brcrit * p.bt)^2 * jxbs[i]))\n", - " println(T_VISC[i] / ( (brcrit / p.bt)^2 * jxbs[i]))\n", - "\n", - " #T_EM ∝ S ξ̂ (br/Bφ)² Im[-Δ̂(Q)⁻¹]\n", - " #T_visc ∝ 2 P (Q0 − Q)\n", - "\n", - "\n", - " xmi = Qmin\n", - " xma = Qmax\n", - "\n", - " \"\"\"\n", - " p1 = plot(Qs, imag.(Δs), label=\"Im(Δ)\", lw=2, xlim=(xmi, xma))\n", - " #plot!(p1, Qs, real.(Δs), label=\"Re(Δ)\", lw=2)\n", - " xlabel!(p1, \"Q\")\n", - " ylabel!(p1, \"Δ\")\n", - " #title!(p1, \"Inner-layer Δ(Q)\")\n", - " \"\"\"\n", - "\n", - " p1 = plot( Qs, T_VISC, label=\"T_V\", lw=2, xlim=(xmi, xma))#,ylim=(-1000,1000))\n", - " plot!(p1, Qs, T_EM, label=\"T_EM\", lw=2)\n", - " vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - " xlabel!(p1, \"Q\")\n", - " ylabel!(p1, \"Torque\")\n", - "\n", - " #p2 = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", - " p2 = plot( Qs, T_VISC, label=\"T_V\", lw=2, xlim=(xmi, xma))#,ylim=(0,500))\n", - " plot!(p2, Qs, T_EM, label=\"T_EM\", lw=2)\n", - " vline!([Qpeak], label=\"peak Q\", linestyle=:dash)\n", - " xlabel!(p2, \"Q\")\n", - " ylabel!(p2, \"Torque\")\n", - "\n", - " p3 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2, xlim=(xmi, xma),ylim=(-1e-2,1e-2))\n", - " plot!(p3, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", - " ylabel!(p3, \"Torque Balance\")\n", - " xlabel!(p3, \"Q\")\n", - " vline!([Qpeak], label=\"Max Balance\", linestyle=:dash)\n", - "\n", - " # find index, q val and bal val of the q closest to Q_e\n", - " println(\"Q_e: \", -tb.params.Q_e)\n", - " idx_closest_Q_e = argmin(abs.(Qs .+ tb.params.Q_e))\n", - " q_closest_Q_e = Qs[idx_closest_Q_e]\n", - " bal_closest_Q_e = bal[idx_closest_Q_e]\n", - " println(\"Closest Q to Q_e: \", q_closest_Q_e, \" with balance value: \", bal_closest_Q_e, \" at index: \", idx_closest_Q_e)\n", - " println(\"B crit: \", brcrit)\n", - " vline!([-tb.params.Q_e], label=\"Q_e\", linestyle=:dashdot, color=:orange)\n", - " vline!([q_closest_Q_e], label=\"Closest Q to Q_e\", linestyle=:dashdot, color=:purple)\n", - "\n", - " #plot(p1, p2, p3, layout=(3,1), size=(800, 1000))\n", - " plot(p3, layout=(1,1))#, size=(800, 1000))\n", - "\n", "end" ] }, { "cell_type": "code", "execution_count": null, - "id": "9", + "id": "4", "metadata": {}, "outputs": [], "source": [ - "# plot jxb vs Qs for surface 1\n", - "# jxbs = [-imag(1.0 / (d + 1e-2)) for d in Δs]\n", - "surface_num = 5\n", - "h5open(h5path, \"r\") do file\n", - " Δs = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"delta\"])\n", - " Qs = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"Q\"])\n", - " bal = read(file[\"Tearing\"][\"CriticalResonantField\"][\"Scan\"][\"surface_$(surface_num)\"][\"balance\"])\n", - " jxbs = [-imag(1.0 / (d + 1e-2)) for d in Δs]\n", - " aplot = plot(Qs, jxbs, label=\"jxb\", lw=2)\n", - " xlabel!(\"Q\")\n", - " ylabel!(\"jxb\")\n", - " title!(\"jxb vs Q for surface $(surface_num)\")\n", - " println(\"max of balance: \", maximum(bal))\n", - " println(\"max of jxb: \", maximum(jxbs))\n", - " println(\"bcrit: \", read(file[\"Tearing\"][\"CriticalResonantField\"][\"br_crit\"]))\n", - " println(\"Qpeak: \", read(file[\"Tearing\"][\"CriticalResonantField\"][\"Qpeak\"]))\n", - " println(\"Q_e: \", read(file[\"Tearing\"][\"PerSurface\"][\"Q_e\"]))\n", - " # plot balance vs q with bcrit as vertical line\n", - " p2 = plot(Qs, real.(bal), label=\"Re(balance)\", lw=2,xlim=(-.2,.2),ylim=(-1e-2,1e-2))\n", - " plot!(p2, Qs, imag.(bal), label=\"Im(balance)\", lw=2)\n", - " xlabel!(p2, \"Q\")\n", - " ylabel!(p2, \"balance\")\n", - " title!(p2, \"2P(Q0-Q)/jxb - surface $(surface_num)\")\n", - " #vline!(p2, [read(file[\"Tearing\"][\"CriticalResonantField\"][\"br_crit\"])], label=\"bcrit\", lw=2, lc=:red)\n", - " # add Q_e as vertical line\n", - " vline!(p2, [read(file[\"Tearing\"][\"PerSurface\"][\"Q_e\"])[surface_num]], label=\"Q_e\", lw=2, lc=:green)\n", - " vline!(p2, [read(file[\"Tearing\"][\"PerSurface\"][\"Q_i\"])[surface_num]], label=\"Q_i\", lw=2, lc=:blue)\n", - " vline!(p2, [read(file[\"Tearing\"][\"CriticalResonantField\"][\"Qpeak\"])[surface_num]], label=\"Qpeak\", lw=2, lc=:orange)\n", - " #display(aplot)\n", - " display(p2)\n", - "\n", - "end\n", - "\n", - "\"\"\"\n", - "Local maxima indices: [104, 103] with values: [80.15320925995013, 79.66428209429431] and corresponding Qs: [0.35175879396984927, 0.25125628140703515] closest Q to Q_e: -0.35175879396984927 closest Q to Q_i: 0.35175879396984927\n", - "Warning: The first local maximum may correspond to an electron or ion diamagnetic resonance. Selecting the second local maximum instead.\n", - "Selected local maximum index: 103 with value: 79.66428209429431 and corresponding Q: 0.25125628140703515\n", - "\"\"\"" + "plot_all_vs_rational_q(h5path)" ] }, { "cell_type": "code", "execution_count": null, - "id": "10", + "id": "5", "metadata": {}, "outputs": [], "source": [ - "# Plot bcrit vs q surface\n", + "# Plot All Inner-layer Δ(Q) and Torque Balance vs Q for each rational surface\n", "\n", - "# print all contents of bcrit /scan /surface 1/\n", "h5open(h5path, \"r\") do file\n", " bcrit = file[\"Tearing\"][\"CriticalResonantField\"]\n", "\n", @@ -368,17 +135,15 @@ { "cell_type": "code", "execution_count": null, - "id": "11", + "id": "6", "metadata": {}, "outputs": [], "source": [ "p_eq = Analysis.Equilibrium.plot_equilibrium_summary(h5path)\n", "p_ffs = Analysis.ForceFreeStates.plot_ffs_summary(h5path)\n", - "#p_pe = Analysis.PerturbedEquilibrium.plot_perturbed_equilibrium_summary(h5path)\n", "\n", "display(p_eq)\n", - "display(p_ffs)\n", - "#display(p_pe)" + "display(p_ffs)" ] } ], From 674efa402a83310006b724a7fd92aa6b1ac5fbee Mon Sep 17 00:00:00 2001 From: ebursch <76970916+ebursch@users.noreply.github.com> Date: Fri, 21 Aug 2026 10:53:21 -0400 Subject: [PATCH 9/9] Added bcrit profile inputs for angular momentum diffusivity --- .../gpec.toml | 4 +- .../slayer_ex.ipynb | 10 +- .../TkMkr_D3Dlike_Hmode_kinetic.h5 | Bin 57472 -> 69792 bytes src/Tearing/Runner/run_slayer.jl | 145 +++++++++++++++--- 4 files changed, 132 insertions(+), 27 deletions(-) diff --git a/examples/DIIID-like_SLAYER_and_bcrit_example/gpec.toml b/examples/DIIID-like_SLAYER_and_bcrit_example/gpec.toml index b00fad0cc..9b37ce9b4 100644 --- a/examples/DIIID-like_SLAYER_and_bcrit_example/gpec.toml +++ b/examples/DIIID-like_SLAYER_and_bcrit_example/gpec.toml @@ -92,6 +92,6 @@ enabled = true # Run CriticalResonantFi Qmin = -10 # Minimum normalized rotation scanned Qmax = 10 # Maximum normalized rotation scanned n = 2000 # Number of rotation points scanned -viscous_input_type = "angular_momentum_diffusivity" # Either "angular_momentum_diffusivity" or "magnetic_prandtl_number" -viscous_input = 1 # Either Prandlt number or angular momentum diffusivity (based on viscous_input_type). Takes in either an array across q surfaces, a single value for all, or false, which falls back on chi_perp ~ chi_e, electron thermal diffusivity. +viscous_input_type = "magnetic_prandtl_number" # "angular_momentum_diffusivity" # Either "angular_momentum_diffusivity" or "magnetic_prandtl_number" +viscous_input = "test_ang_mom_diff" # Either Prandlt number or angular momentum diffusivity (based on viscous_input_type). Takes in either a string name for the .h5 profile file, a single value for all, or false, which falls back on chi_perp ~ chi_e, electron thermal diffusivity. store_scan = true # Per surface torque and inner layer quantities diff --git a/examples/DIIID-like_SLAYER_and_bcrit_example/slayer_ex.ipynb b/examples/DIIID-like_SLAYER_and_bcrit_example/slayer_ex.ipynb index 4e59b802d..1b3ee30f5 100644 --- a/examples/DIIID-like_SLAYER_and_bcrit_example/slayer_ex.ipynb +++ b/examples/DIIID-like_SLAYER_and_bcrit_example/slayer_ex.ipynb @@ -83,15 +83,21 @@ " sval = [read(scan[\"surface_$(i)\"][\"sval\"]) for i in eachindex(rational_q)]\n", " Q0 = [read(scan[\"surface_$(i)\"][\"Q0\"]) for i in eachindex(rational_q)]\n", " max_balance = maximum.(bal)\n", + " #read eta from persurface\n", + " eta = read(tearing[\"PerSurface\"][\"eta\"])\n", + " # Calculate angular momentum diffusivity\n", + " # P_here = (4π * 1e-7) * abs(chi_here) / eta_here\n", + " ang_mom_diff = P .* eta / (4π * 1e-7)\n", "\n", - " fig = plot(layout=(3, 2), size=(1000, 1200))\n", + " fig = plot(layout=(4, 2), size=(1000, 1200))\n", " plot!(fig[1], rational_q, bcrit; marker=:circle, lw=2, xlabel=\"Rational Surface (q)\", ylabel=\"Critical Resonant Field (T)\", legend=false)\n", " plot!(fig[2], rational_q, max_balance; marker=:circle, lw=2, xlabel=\"Rational Surface (q)\", ylabel=\"Maximum (Torque Balance)\", legend=false)\n", " plot!(fig[3], rational_q, P; marker=:circle, lw=2, xlabel=\"Rational Surface (q)\", ylabel=\"P\", legend=false)\n", " plot!(fig[4], rational_q, lu; marker=:circle, lw=2, xlabel=\"Rational Surface (q)\", ylabel=\"Lundquist Number\", legend=false)\n", " plot!(fig[5], rational_q, sval; marker=:circle, lw=2, xlabel=\"Rational Surface (q)\", ylabel=\"Magnetic Shear\", legend=false)\n", " plot!(fig[6], rational_q, Q0; marker=:circle, lw=2, xlabel=\"Rational Surface (q)\", ylabel=\"Q0\", legend=false)\n", - "\n", + " plot!(fig[7], rational_q, ang_mom_diff; marker=:circle, lw=2, xlabel=\"Rational Surface (q)\", ylabel=\"Angular Momentum Diffusivity\", legend=false)\n", + " plot!(fig[8], rational_q, eta; marker=:circle, lw=2, xlabel=\"Rational Surface (q)\", ylabel=\"Resistivity (η)\", legend=false)\n", " display(fig)\n", " #return fig\n", " end\n", diff --git a/examples/DIIID-like_ideal_example/TkMkr_D3Dlike_Hmode_kinetic.h5 b/examples/DIIID-like_ideal_example/TkMkr_D3Dlike_Hmode_kinetic.h5 index 2f084f080315cfd157a6c6ed58ddd06cd72bf2e3..4ee95ff2d875c73e8c03e421e9af12ce6393e823 100644 GIT binary patch delta 885 zcmZuvO=uHA6#iy6+axX2ZAc}kDJcq8L{MnS!HbE>Ce;>Wlaoj{q1iNRO%qHHRSSt; z^wuQBgP23~`=KRwh88XahZd(8!=`^OlG{%)=GK$OZnMwS>s!2(Z;FU>Uq{|Z~ zLJ%x~=ml9@m%JmA03!CgJb*~5pIB06J%IJP(GK2Q`IZ&nV<|k@VMMWeG1U(jh+V;8 zt8R2-%1k@~Cp857*jDbh9VvSSKQ^sm!O@oPx^cMTFgLM-tqahO@4DREebf9EPQ@dT z%(?+;XUCq}XLQ4Dm!0321u$m~8BQpu{8Lzt3cv`|m8=B@k1p zc52ep=9Q?@kH@)^=JL9#rO$HhG<7Mjm!`NQE~?t?zJF>~)t4nMoyCGSpHZWUGu#nN zWj!F;N+v_O%z~z77U$JMv7l!4T#o-uLX%5cd8sE^`(YSe(n(ikdHh^FG9!#)_SU7I jj}R{%2to)SXpa9K>>7JS^bEG6oopWIkbNKetWJLbx=WkB delta 71 zcmZ3mkfq@u^8^j%h6fB2wPmFl86cnoO0QsoFc=wFHzv#a3JEd@fCUipn p isa SLAYERParameters, params) || - throw(ArgumentError("CriticalResonantField requires SLAYERParameters; run SLAYER first or provide compatible params.")) + throw(ArgumentError( + "CriticalResonantField requires SLAYERParameters; " * + "run SLAYER first or provide compatible params." + )) surface_index = Int[] Qpeak_vec = Float64[] @@ -385,37 +431,77 @@ function run_critical_resonant_field(equil, intr, ctrl; dir_path="./", slayer_re P_vec = Float64[] scan_data = NamedTuple[] + chi_vec = nothing + P_input = nothing + use_P = false + if ctrl.viscous_input_type === "angular_momentum_diffusivity" + if ctrl.viscous_input === false chi_vec = nothing - use_P = false + elseif ctrl.viscous_input isa AbstractArray + length(ctrl.viscous_input) == length(params) || + throw(ArgumentError( + "CriticalResonantField viscous_input has length " * + "$(length(ctrl.viscous_input)), expected $(length(params))." + )) chi_vec = ctrl.viscous_input - use_P = false + elseif ctrl.viscous_input isa Number - chi_vec = fill(ctrl.viscous_input, length(params)) - use_P = false + chi_vec = fill(Float64(ctrl.viscous_input), length(params)) + + elseif ctrl.viscous_input isa String + viscous_profile === nothing && + throw(ArgumentError( + "CriticalResonantField profile " * + "'$(ctrl.viscous_input)' was not loaded." + )) + chi_vec = viscous_profile + else - throw(ArgumentError("Invalid viscous_input for angular_momentum_diffusivity.")) + throw(ArgumentError( + "Invalid viscous_input for angular_momentum_diffusivity." + )) end elseif ctrl.viscous_input_type === "magnetic_prandtl_number" - chi_vec = nothing + use_P = true + if ctrl.viscous_input isa AbstractArray - P_vec = ctrl.viscous_input + length(ctrl.viscous_input) == length(params) || + throw(ArgumentError( + "CriticalResonantField viscous_input has length " * + "$(length(ctrl.viscous_input)), expected $(length(params))." + )) + P_input = ctrl.viscous_input + elseif ctrl.viscous_input isa Number - P_vec = fill(ctrl.viscous_input, length(params)) + P_input = fill(Float64(ctrl.viscous_input), length(params)) + + elseif ctrl.viscous_input isa String + viscous_profile === nothing && + throw(ArgumentError( + "CriticalResonantField profile " * + "'$(ctrl.viscous_input)' was not loaded." + )) + P_input = viscous_profile + elseif ctrl.viscous_input === false use_P = false + else - throw(ArgumentError("Invalid viscous_input for magnetic_prandtl_number.")) + throw(ArgumentError( + "Invalid viscous_input for magnetic_prandtl_number." + )) end else throw(ArgumentError( "Invalid viscous_input_type: $(ctrl.viscous_input_type). " * - "Must be 'angular_momentum_diffusivity' or 'magnetic_prandtl_number'." + "Must be 'angular_momentum_diffusivity' or " * + "'magnetic_prandtl_number'." )) end @@ -427,20 +513,29 @@ function run_critical_resonant_field(equil, intr, ctrl; dir_path="./", slayer_re eta_here = p.eta if use_P - P_here = P_vec[isurf] + P_here = P_input isa AbstractArray ? + Float64(P_input[isurf]) : + _eval(P_input, psi_here) + elseif chi_vec === nothing - try - chi_here = _eval(chi_prof, psi_here) - catch + if chi_prof === nothing @warn "CriticalResonantField: chi_prof is not provided, using control chi_perp as fallback." chi_here = slayer_ctrl.chi_perp + else + chi_here = _eval(chi_prof, psi_here) end + P_here = (4π * 1e-7) * abs(chi_here) / eta_here + else - chi_here = chi_vec[isurf] + chi_here = chi_vec isa AbstractArray ? + Float64(chi_vec[isurf]) : + _eval(chi_vec, psi_here) + P_here = (4π * 1e-7) * abs(chi_here) / eta_here end + if P_here < 1 @warn "CriticalResonantField: P < 1 at surface $isurf (P = $P_here)." end @@ -454,7 +549,7 @@ function run_critical_resonant_field(equil, intr, ctrl; dir_path="./", slayer_re p.sval_r ) - Qs, bal, Qpeak, br_crit, Qpeak_ind, Δs = + Qs, bal, Qpeak, br_crit, _, Δs = torque_balance_scan( tb; Qmin=ctrl.Qmin, @@ -607,11 +702,15 @@ function run_slayer(equil, surfaces::AbstractVector, delta_prime_matrix::Abstrac rational_psi = Float64[surfaces[p.ising].psifac for p in params] rational_q = Float64[surfaces[p.ising].q for p in params] - # include critical resonant filed workflow here + # include critical resonant field workflow here if control.critical_resonant_field.enabled slayer_result = run_slayer_from_inputs(params, dp, control; rational_psi=rational_psi, rational_q=rational_q) crf_result = run_critical_resonant_field(equil, surfaces, control; - dir_path=dir_path, slayer_result=slayer_result, profiles=profiles, chi_prof=chi_perp) + dir_path=dir_path, + slayer_result=slayer_result, + profiles=profiles, + chi_prof=chi_perp, + viscous_profile=loaded.viscous_input) combined_result = SLAYERResult( slayer_result.enabled, slayer_result.control,