From d6f120ca4946df32d05d154fb17d222917623549 Mon Sep 17 00:00:00 2001 From: Matthew Pharr Date: Mon, 19 Oct 2026 09:34:34 +0200 Subject: [PATCH 01/12] InnerLayer.GGJ - REFACTOR! - Solve the :ray BVP with the Galerkin solver --- docs/src/citations.md | 2 +- .../inner_layer/convergence_Sinvariance.png | Bin 52336 -> 51521 bytes .../make_convergence_Sinvariance.jl | 6 +- .../inner_layer/make_solution_profiles.jl | 15 +- .../figures/inner_layer/solution_profiles.png | Bin 57570 -> 53329 bytes docs/src/figures/manifest.toml | 10 +- docs/src/inner_layer.md | 50 +- regression-harness/cases/ggj_reference.toml | 4 +- regression-harness/src/runner.jl | 10 +- src/ForceFreeStates/CoreTypes.jl | 2 +- src/InnerLayer/GGJ/GGJ.jl | 16 +- src/InnerLayer/GGJ/Galerkin.jl | 212 ++++-- src/InnerLayer/GGJ/InnerAsymptotics.jl | 81 ++- src/InnerLayer/GGJ/Ray.jl | 621 +++--------------- src/InnerLayer/GGJ/RayAsymptotics.jl | 237 ------- test/runtests_innerlayer.jl | 20 +- 16 files changed, 370 insertions(+), 916 deletions(-) delete mode 100644 src/InnerLayer/GGJ/RayAsymptotics.jl diff --git a/docs/src/citations.md b/docs/src/citations.md index dd8ef7546..a447cfd34 100644 --- a/docs/src/citations.md +++ b/docs/src/citations.md @@ -104,7 +104,7 @@ Provides an efficient algorithm for computing the full Δ' matrix (coupling betw > *Physics of Plasmas* **27**, 012506 (2020). > DOI: [10.1063/1.5134999](https://doi.org/10.1063/1.5134999) -Constructs the Wasow large-``x`` asymptotic basis (the `inps` kernel) that supplies the far-field boundary condition for every GGJ InnerLayer backend — the Galerkin solver and the rotated-contour collocation (`:ray`) solver alike. +Constructs the Wasow large-``x`` asymptotic basis (the `inps` kernel) that supplies the far-field boundary condition for every GGJ InnerLayer backend — the traditional Galerkin solver and the rotated-contour (`:ray`) solver alike. --- diff --git a/docs/src/figures/inner_layer/convergence_Sinvariance.png b/docs/src/figures/inner_layer/convergence_Sinvariance.png index d8b550822530a547073755a57db8762df23bfa33..861e993c4af375105ceb9d8cb7a00060ab91f968 100644 GIT binary patch literal 51521 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�Em#z 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%0A8Da-@9du~(`j%a9ihT^*0@PQ))<|FDvXbdD;Ltc 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 YpR1}$6PLER3)kLZj`QqO(&gL!1sa|Rm;e9( literal 52336 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

cz{R+x| zW^zQzB2+_If=Ysiyay~1`YEK3X=ghmelXv^GcCcVY~VyYtYIYg>5asjFeZNf z^a;yKA>0o_#0)3z^y$<1JX{1mvLvd*#7;wl{`tjX50zB(Zb+@x(dd8g0HYG7d$h6| zL9O)lZQs878^;lQh3*z495R09OA~l}QE!lL6|Ainu&Q99#os)6eI+hCGgIHd02w44 zFr_<-xV^-M7yVhudlfQ((h5 zBiQ&ul$3BBu+9~&t*l_^z!GiWO5P(XU<{5JR3$M_ZI98p)NTU*5ojRjg?-RH?MvSg{jOFK9SuT%Qu~J2D>z zqTyX^X+drKjHqTA`twH&C;-hfdeHapSr>bYMsY(JJ_>{B+txN6KoR&A;$d>iAM~N9 z3YUY~L4adS1y+bZ~te9c_u18am1dF)XQz2CF<5h?obRd?IS z&yn~CHK`x4eZJ4Up{+B<;r^?YbRUc3LMP<;coe!Sl;ZZ2Gb;7d_FZaiY$O1%4D((l zEN58Q`0#K#tOOFmCz+WsHdqfc=FVNa07^jq6&N)XS*slRpBLag02g~OJ>VD}9UPGg zao6f1#mh0o5EZ2ycWrKC3x8sd&|O|GS1=@aST)tvG5a=#bAT-Z$~#YjhzBUfl8y`w zfyDsbhmZ!Rs|up4t}YNznQ0TS5P}-G>aep9t^qFrd!bL%=?zvzZKI=utxoLDPa<*g z92}$Xq8wKNH&HeTMjA9Z$lkX#HBr{wU=IOqQADc<-?>ahM+ZHzB!syD znk^zjWpc*Jwy^l>=~;rUjf{v8VXei4kXU5$hYz02$a|r&`Soy_X=!z1(%R$OCc{4- zZ0u1BMaqw%cvnegFV?eqtfDboqMzrd+YFUrD-(a2=KKm$w_HD-m^@XhqsI3jJ3vZ) z07)AoZ{V@#iblb?7Li5|u4-Gxk?Qb{A%&vH0ETkd-%4n_{rp%w$86R@d37-hXRN2! zIKmKy%9+`C>D;+KL^E=pL#ZYDCV2HcUnD0_quWKdi0uF}Kp6r>%YE$FEUGppOE3(b z`>hFYOMKu+GtLEI83x8!WW9Iq-8+zFy$=NleG6(gQVhtr1N-;0s;DW<0{3D}MAS*dCtgQY zemWS@qTs%EZ*`qaPk^4$T;WhqpYp5T;a{K4*+gPz=dYHE+|rRDfx{a?fxLlqihP2h z$7S3l$N*MP0=Rv)O~QiA39<8vD|+?F$VgO*mw=2GHs;^He*H;R zjD=oUSb$P1^2-8^5k_zzIm5RCU8CE<9yI|V_mt-Mk7$>`-2#FWoCDR>pwo_CWtzTx zea>+&3Cn&jcUmcP0TKL)0EO+mD2sR~LBUkx_1Iqm+br#t|M>AaWo2^sEvtUs!@HJl zQ>N>Jc|yE)%d=ei_jSw@D21F+4D$$2cq)C#V1b0U9T{|GG}?__@y#85eNWvu#0p{< zJ4=#yJfwq{#ypt3f>#a&Tb#2?W!FF9CrZA5a5Uu4fQ*=$ zWmvLlg)Hq*j9b@BIskn1$JlU8;R*n4!rJcWxCW3(DFaayu_$sIEi|@LhwEU_VJRrw zknZ95%4uqBEDK;XzJFg3{LFmOD9|HY00`;P;o;J&k8v_!W*};NPeon!)Xy(c1c=a& z8ry@TNZ^?2>*49?{~bYj_%P=B&VY;BsQ>-j731t^enif&;>i+}7%Ikef_%tJ_>a+L zA!~wwpM3&L)Pu8~AhPfXjIONE1s=#>AYHQ(zk#)$Rj)#PpwaI}PR0y#BP?4l ztbs!)w+Dyyp@>*k&>cE--_THAVq#!`A7l5ZS!P_T_U=0fLijnu{>RnuQeTNf51fNX zT`-6q%+SU(Xmd@?6xbc$H$rt4FeJBsH#jwgiBLF#uc69gFx=P-ZgOh`9in;Ks}9kP zDRLaWO{4;(^?y=ON{TsfMPee4@_CZ1%*tnG3lzDlpI-`-iiOi$g6#Q@z3kdKTg= z$-aI4v*2IaDl5l910hhjPo5;(zdsv=FC)JQ*kgHaZWSpVV2**2(QoAeVjR}QvhCh% zTORO3XUcWL7ZqU0s!iqrsf)GK9SFv;HyzkdJEjpC@H_c zOT%&;`4lGur?j)Z9i}bVDp)WiQI7 zzP=)O5CHgzk7}PmU#6!ErW#6^dcvNaB_0YA84uQ2=4vwf4w@dV)u81&z(E}96)u#@ z%uJE_D6||_AhW=WBN~j2jJ{}P9b{?7V`?zx5b*@OI238d+#=Xaa0AG(IIlQQI_VD& zDTiWS;MJ>=ZFEKi<0KG2S{*1FlFAXn=24gqK%~Pm2EQ17n`MvLgj7^#%m#6Ba$>0T z8Y*`JW-dSnDMpH=d$?~Zew`If0Q1$})x|7owOjWZqlZ_W(=PRu+?=09qdg>2eN#`o z>I!-HAC{Wo!`?tRU}N_qM8OsV{79fC8T|YYpZXJ2v{89XWStqTSa*gw^Ku-){;{z{ zM|Kg(QYCcfqL#%?>WIEiFPmIv??v~n2Ufn_ra6X46C|4bgiE`*Vh#pM4Ti8!o;U#zIy5+F zjY~pR)bm?OzO0~NZDHZ-?~lzgGBrIRlLwHxkD48!gH8-XDl_nYcQ>uEcuGi0qKHz- zAVeUzq<#Os5mkhR06AV*M_!AE@!%0Pf2OCEr){JkG#&@djoORzDs%3!^{KR46t6Dy zf7l&AzkQ-E-~vEYib8D!;|Yce3?N2%vxEsG);8IZvzNdn-AW+r1<{70w73Y$i!2EY zcOGmmWzXny?55Bou157KLf*zmy2Ar?8Gu3@Nj$FPG3CpkAi(xALJ*MEl0bo*7@|T| zh*ybLR_uj-*;Hs#&47_hu`p_zFUYUx0OA{0Tu&ZO%*qNIGbhR?cK+D~A0Xx>8K|k7 zn)dAI>jDvje1Q7@erEkKv=|9-ZDLnDi&h+Mkh<^)1Y{My3=RhOJ7=ZclL(R-tsqj? zN=$sb0hZQ&3Xh3-gm}iPlu>wjdgebEpnkLW({0sHYHvor+{Pn1jy&JH5MfKZ@;KuG zo;`)L1?$V0zUyKC($ux%V@D*C9+<1QthcqK=t>V*Z{Du4_HNrIsDViGU{|PQFb0kc zjVEYW*x7ASMgN2m6=3DPl>){{eDZqSF%E!Ihpo%8BY~ow0nAK2A!@f*akNVtGL6Q` z!;9^!CpJFxO+wEcT73r=4d_Tdp$SSD^bcTOJf{F2fy$ol)lL2T_cc!5#3UY5frgF_ zJQTfC^8dDL?65SKNKpQ(xCQ(tNy*RK5=6*Y!lZA zw6V3htUG^&2oxgj0|s%F#f{40f7yuHX_=n3wB^T+jcU8s-xdRoxxasRNA?-}#jDh8 zdTs63pO?L%qo%(1>{N@9B43%&z&$^9OuilzT>5=4#&+r~hOc*rGqzUrb z&*GN1sGZh!b~-;yIw1bHAGTxa27zy_OYp1V^I0OU(!hH_&{Bc264ki9WcmjNid_D2 z7dL(D=y#skAxe1ZKGz}*XkHKzz&6l%e|n(CNyF^2NX7dXza>)N$5hmT4GKM}A=C6d zHkR$eRl%v>zkibuJY)4mmW;JnX{pV{CST8W zN{v2?e-L*~V^kJ4`GHJ2!XFzK+ln+z{3RTwhw1E?aMopp_E26*_?`MuT%jr_I?ym7 z)3&YXwH6?mckiJ7gP;G=smB9ZfAQe?f`?l;x@sLh{ZH zkt3o!pwqzTp2#zk5CvP^1Bo23`M8C0)V`YiOlu3F}F8E|T(} z+42iX5#iuGK6IX7@gw@m`fvYPil6ySsROqh%|3tdsR6w zz6b?zlXzRXs@l%RVyr<>4^2M6i*wtapL>$!Ydf(>&~E{D0@n8sJsueVjxjA}y_mZ( z63DeEr7?5rP|~QG1Wmh;er@+7$GoVSKSXaC+Sm-qit%tI7f_2Z7+~Tb8A_1ia$I9V zwCmeJM}){{AgAL7V5+Mui*^p{B^3Ft=IGX=hjcvcTb5FzXSC$H&yiabF*Z1jO zCSft-|MnqKRn_>$w>ff`A3qfnXjsg@)7sd5N;kN9B5hI3^vo^uukMa%&mRmvm0P=+ z6(;CK6V`OOzBB)3LYu;y7Ow9dqny7Y9kWc6+Pqlw`wz*UPY*j3C-d#2e|^@{Rj+%G zs-wrhXGv9(x;CqBYewFjsNCT3z7iRBh_PfS%}nOORBXQZbfa6Z@TM%iHy@oRYr}Ry zBelnF6{l9mr~4Bt6K);QwEpW@S^55SJn>t%%W=H4VQvD|WQRP(TK=3(a$jW+5?U|v z6uWBf^HyhQvBh>Rxv}~!>yA}Utv=)1iA_}(s(C++=!P0feA;(DT}<%IP;iy^#uWi( zi=$K;jW@=QCAT=7@#zSAkl%E7%l*7-`se?Lx;G8y`t7=hH4~L2Qz0cyLgo-9Q-ny! zEHWo#o-2_lq|8E*WJ)44B}t}`A+t=GN#^OlK6Tyq|304McJbqkXuv0Q8E>Wy;q~B?1fgK4=I zi-Ohl^~`)`-$9B%W#s%vulxt>ArO4mXX7@kbQKLu2047Hsh@xK7JbLf;*=g+R{pZ( zl=Ta*OL@oij`PIXM_%D7uuBhH?DT}={bN(tY^SIQI8yw1F&&XFzLaXDGsPo!V++#jW5!aSzgEb*at82c=G z&Mli|MVcMm%q?`~TfzLY3wF^^b_TCq2WuN;@U`zRx?;bs2)GUm#Cqk{l zbZf_J3}4rtlTNotS=#%Fb?d=``h#_R8%BHt<7di2fk#mv*{jzbpC~$(`^Zltn3f@ zh|XRi)uR(H2xJxK**J5iBv$#;y~15BT8T85&2>{B7|FP@#a=fZI`R5;(Ax3a-a~IH zUy?34M7vI8G4D36wGNW!F%s?FHJ;TodT2U3-8g6C=kh%gaT#Dnz#ctTXDZ=i@DIm$ zM)?+4-9ooZW_-M7{|yE*+O6tav?%pXwJC8is1er*0 z+UsLmI7r{bzg+jc;}(~VT&lk^2xLcVB-Wpk@8klVLWchK?c=|p*O|iAJ$U-}ym#0u z_7*lqC%ACszb5tEq2-ee$VpsALc;4(p*lO8*CC+d?+nR@>h>~eU)tF;s(GGDY-;Jk z{q}cGzbv+U9wTk-tARrqCC>C4jqdZ~*Aa_Bj(s$S<8G`W|IYB9?&w>y1{77LH<#%y z`rFs4b)H?VRy?(Ie3z%NmM$eu+#ZPA-gi5nf@9$G^>bB||CF}}`OK&l4s0ed=?i1m zI27_wY~}f}weQq!i&uU!NqpbWx)!rKpjcx6aZ9oy`c>1~N6t6>>@%xHzx@v^IS(Bw ztF9(=Xkb?&*6t)DyPj)7zwkGfCmbIQ4H^!l=d-C;IJGe0oI1UJ?tqKWw>Jt`Y3m5M zLFQ8jV?2pqd3m7-+Ky+=Sfg_XO803_P6u0C*TJW1D61^NO>{eh&4-ei$ue9X z(D=q>9s+_xP<}zi<18kQV)fJAp9w{VWp~l_D_45^`}Z+0j1CNZQaef<#x3`KtX`^| z>~Wo~B~Z)tskN}9R8`TpOO_x@%@+7he2+<%BdIZG$s%FY*X=S@3>XE_1K>mS>C?6H zm0vWh{%KO|Y$bl1-nqQp#sG#q*5+E#r378RJ{L6%TtQb>R^W#63m=X8&(x7f?MM{4 zGH#1&YH3|2g{+#-G$=5z*@Ra%>F*jLAxYcW+Lwlc09D|gddlFK7*L-kMn}I||IJlY zABU^+ah zGDNY*9ch8yG^&xQk`>G74YXdVD<2SPlKPemPSW_}uYp+^(cZDP?u-BLv~ZuVgn3I^ zU*1)Go9EExVaLDUzqkA4?YA08_uykiK}rf=1k2|fL@k5#8a)F*sIOkVg4LH68S(Ax zhW9iexma8pjx*0`M+q%ZF^?uHRd=zmO58fL<=L!N*}iqUT)Xw}L$FyiNU zh3U?&c;MlJcexIf_PC#!-^3Jh&4IR=_6y8sGV53mld&X5!9aHMS=XPB-$KOF)cNP; zTBDv5Nt=ljm(BbJQomj_zz-bg0Fn*ylcs$?P}dig^52V=56pJDSa7d|pO;8d z=*aF7gWUQikt=%|Rcc7p!3YlS$qS>YnKs|l6cp-EJp^h3rtnxA3`cc<`VMtDI#4>r z&gWLfv%3oHvQ?6qU5n25+}SxI_-fK;OM%&r`nWSI_dV+Rw%^88oo1--tI^{+C~R+m z6d6q%6wowe#%Qy=ecOnvZShy)2R#`DgHq)9lNnkJkx;vzKGnBziV5Z$9J&&;6p#H=zez6b{8F|*CjmvkSXWuGl zPPp0Y#`^8gSG@Qs@4mU4-XIx?)EcFBkPdp@Dkq;RB=6gKz}d1-=^K#;n??;41|PeC zM(;lDg|5cl$am0QNH@JxNbV>8-Jm;+J2K#0jAF= zATkh%>{4)VHLO(a0II?_)pqo|?^-j#%g=bU_brHaJ9hXy?>KfzrpNjHH7jYgi2aO= zr^BmHU(+FHp(IUIKJoE7^77MEzSFzkk$UTob{;6(kWEtVi+o4QA9E>5xrE$_ig#{D zOksHx%4q}zv?1_?)znHCTOKu0OEkaf-yQ6Hz>{#L4Ta>bj$HW1KqFc3_U-RL zfo>RB(m{uZ>Tb^2ZQmSpgTi*Bwt(8_TM-O2rYCO(DV%)D)Lojq?~da7HR}9#u`1#F z#2>0kT8@W$G_{J&_EsI)@uScYbsyTK8zpW!6TR#1D$#lReJlOzF`{#J13V@yj(PQw z+1axo$tEkrIujnjW33wqcIe~m-}wN6H?U_By@A&%C&^d<;@enRIbxlWv7k`{4tWVc zXDO-AAcK{xFOPk8_(O-rQhlsQfqwtz+p6v^W8uDsBhxbqxZ}0k0$O$5%|AzD0foOt zn3spVAX{<4`Ru1#QmrK752LjT_;Q=tx(Z(^9!+gszc;p}*H?OGT~Z=lbqcs0;tkH` zuXS~n11&gGb?&6oODchK%(F6!{+s=H8@l&gi1rBN{BOe<0G6XUIoe&kvQh9{HVOVW zCS3(N1WCZpG)v{=eq=wS^Jelfiza(zlN!6bpG}>NIvQ%I+J9G;$9^Hu{i64gxN}TM zq%IIuo>)vXO!m-T87lPKs5S86x##wN@KDV4ogX8&^=(;q9F;R-AIScEUNAeJhPp25 z#jvxq+w9~!{#)(5?}BA4ni2}D80&t$_IvwjmY+M?`#tCUE~@+}ritdx5~7qdddh zwgp?KNTY(pCK5kr5nE1 z2huYdI}2oM+>T4=tltPyWebc7Ff4eU*th>gmPAX5@ZRr2txfUl%`XLbb77GbNe~-!JJUzsjM!b)~21Q$*pl z$5;B;O&QG^UsYFsr;R97j(%>)qJ6?NJ!t!j=2urUDcftJFANNwoE5OVvyqst~<SP0Sf~Tbs~Dp9tR3N#kG4odTxlw5>ni7WZe)+L7a1dP(~J6y8&r-Q-g({W&SO zd4uaEnA~qN_xE-w> zLgiOf+IiuUncHcX>2epm$?UO{H*~Y71it1aK`roeE-q4A>6Mj|>!SZ9!D>z3sw?wl z;{|nBMISp%8gxDvDajUbzvWil8oc$LL)=`tHTjFyL3hEJGYh5EET7z393FdWY$!dQ z(9(9|{xI&x9~);K$z7i(sT&iw@uPaEhk|-A$0Yko-;GYyBFjs5Kd)!Uwl5q=dgxZ0 zCm9;H*jstlNGg!<~$7;t59=$MXn`64s`Mkh3(Xg63`;?zn@wwrR z%EU7Z{by{SE~S3d*41St59GE?SzHP7E9H;UR%++}I8mD!plM=vZL;W$(F<0VPyP3s zZ%nm(KAq&@u4cFH`D6br7YbVjfsQ=M@Hp-1W|izyRCmi(veP#^r5CF<)HA1E&5Y1) z?pyNRU9ZS%snk=X@@{C~tXq4VlLx(VW5mYb*ifkRk%z^aF0OA1RQHv4ZdeJv;0x6y zn{SgZs+`v-sz}UAn#ejgl;*r>o=E1EE#)+y!qjs*rgi#L{1X}W`9A_n?lr&O4bltL zGKo>;JCY5&T+-O+6}@HuM&j^3rwE0?OR3lPcwBRfXe$qT9HA2%UtNF0c2C#VPl;Fa zW4~1V(LADkJ%f{v$MS;GlP{+{sai@z9_ZWVJJ8?RC?{i#;k$7l)XL~MCx676EGy;1 z;w|#JwD)!5!cFHdve?)NFe)CF(2cphzLF)gI{n^BDz#yMgjk0%wpnoGvxHZiH3@vp zyE2alS1~iSC#0U5lXQ9+$eZ457MLl&*JU}{_1aOdU%$EOiz7pL?xx@W@}oSlA)cL2 zn7Ej>!kiH;28tJjaUZyhUUE>L)biT>GV~GMS0=hAH;Ld<(VZ^eL*X2|#IjXfqK=8J z|B@G_o085=YyEO&D_QpaE>Z5$#=Ol19}i~7`gOUJ?=DY$1bTi(H+%SPr&DXwj(ygS%fp_oJrERJ^n@t^a$LPYMr`R*t9F{09 zj2cOMG$ePGFR`b;Gqd=Z;~=(bGATVfs!q?~b*GN~Rf<^e!LDHo0>mG#JL>g~w-`nX z^BHT%CqE0o>CguVNd|sZYFm{4(cD zd^$~aW##bV2+x)mD|MQAi(NmaX0&&cIOLURTup6;JOFyN<;4h{j-G>kX7c8qseGrm zshMj~iuQ)xGj3G2%6YksZ?5CJZ;2pAM( zQ@`lcv#Iw8%$@gqHtalMjsKuZD_(KeC?Ui%DFz|?& z4hn0Xv)(nr|9eBz?IVS#zV|C%Igfz7z7otHyy2yrH<4%@2H*{*8eww?vTh42kGKrd ze~-mJA6yx7Xlt!K=lyST(dopj`mxztryHu4AIV#;^*S2o=Dsq2s}B7zlLnOFpgem8 zqyHT`kBotiVtZ0!4SOPq-U)QN>Q1HJcowTVMWw@XxxVUDiEfp?63}obLDW~&q+5~n zvQ40(fr8ie&Yk`|CQlmkjSr=Ku{V6<6EuT=3GL}|Avtz{gv81ZEf^F{=vWGXuK_kP z%SCU{z3{7V0ailsfrVR<{+dKEG{mi^x3j56-16=on<;B$w0~Cp0a=rxrLl{}5PBY9 z59c}#hsbohuS|f@fhN^?|3N)txs$cAgDI+CEhYp{V9BmmTolaC$>{=HLQU7r4&-0- zH!yhzWQtx-Hj>H$hsk&5)n~4ilPAUP*){fwXlj)GWQoZ_lLKE%ql_dltX}$1w3Nsd zoA*A&h0HrFPGfEP*p!tfEy;Pg%6f`TBxS-VFz9cWm}bu$eV&?eXH&yug(yE^94^Q~ zK@$JqqTm*j{4n>K>ni57(fb<)+-=f#yq0Cv>{ik0w$-cW2zmH^#*V}@jI2=GGfa-1 zW}{d@zu~cBIH!x$LCS>Rlb7Wz2KOk>UGjOcvPXTP{wOCWXNmb%5)*4QQZ#r&Wd8hk zT#;>DoDIMXbOxKGw`;)DJlsvKthjoT0ES&bXXSiMZ0s@lD2XOyN@3N5uHjoqzCEAW zS4ZgRfjEJI{y=;N8TUT%`N^&hLPRvtF{``>(ZKU*FH4Lzib{w`P_m(LLv3s!2#pDP zNZ{W0mN4PFNX9O)L<_sKgPrJkSrMJsLF9yRj}tV8sifW#d0B7GnZ{80Q0aBtD&Uq>eW`{>HKntCFfZ5Qg&vtm03 z8aIk4=fCP+y11h>_{|h28Yd2R_@FW|rjL>02?Uu3>`KKLK_!4~BO_<^$~=>wIs2{1 z3K~7Gf$`K~mj7J(Fxxw7$vJev@uG|V)cN~_(vvR{z1aY3x4P@qD!SYTSxcAg7KXlk z;Ot$6BHokc(U{fCX0sIMyu3WysqVFvsZs$tii2v+-(Qx@k5&~I=I+_$AsCs}=BgSQ z!hM*3sA^>vLA` z@LJM?`5Z@xj35WGMALS(_F;GmF){!!$6f0e;t3JJ=1?)pl1753g=tv|3PX8s*p7x* zFE9zpIBhFYRTDKJU0NKNkdyt8bv2p!nJ|H~X;5dBUx()`i$rR3)I0MWjd>Q>28LEW zD{_h%tu~f1!uRL}j9Jl8Q5_Di1{cXZrXHjkBG{tjqY|I&Da}+(EiNh&xc?qqT|kT`t$!a-Ji6V{RcqlAN|~sdtOL8KOA}35{4E#emJy zF>)HG8cg(mLF#~%wYOKV z->C$C1bLi)DFv_5hzBSGLNbuu`Sq2lJDq&^SkJlsWwTlo_j|>`c&hpDCT}0RpkN!M zJi@}!{qDs3h}wqMIU4o_wj;t*MWIl(TDRh#Nm_z%kk|@!;UEFc33NY3*kl_RT%G;D zO?xHk{a~ll(JfA2%=@c)_8hZfqw+;(__K8~@fo$-_S_-NAV|);Ek>49>2U!&gSv#F zo>I@i08FTIxxY84de6ryEFyx~rI^YSYOkxS>qWd(lRihmw56Z^oZuk?g8!M4{7eIy zZ-4~GwNZn8eOWN{`>&R~$mJe*jN2e>09*(PFI;93r@*qins9|3{9Wwlga5GbYk5p( z4TiV>`ku0n<IT%f$wUt$AAs}JAW+8U??pzjMn zvIeja?ud}^z^uU)@GO{ci1r6t4Zx#;_!?NR1!#e{I;J$F=Sis zA%32rxJXJbXw_TISy}|WIBYkDhbvcVO^+Nt41pk&mo;1g$;rl;l~YRaK+cnYDo^Jn z-v9b}rSHHli-606Rj-<^LALcEqrqtmSmDyYXYCKt9l$)0%fNTXXOR*E0B{h2*Bt#A zpF^U)+UeC2p~bO>l=MyS_8g5{VDX42a4EQKzuyPxoK1ca2+ctKN+H#qIXV6q4;~`D zWiU&~SOAS<8S+(G5g#NU7-tn09_|3z5g_|vL6rXfdJ4C3 z)T?NDG*$83oQeUFZId`sP`g-)8sq%L`HrqVoOpgCeUo9O@^?sRHcL`YnfVeK6jTrS z3CJSnNzqgK0r(ldqXr=*on2iOH>_)Q_fk{8107mg>pcK;JgCDr-&uj9a1xJLyoB6z z9tXJ1%*UmmA-5U_7DX6_o!(ZTnDmR_AS5ZDASeqAv$<%H91e+0I74KkJtZjU)Y3I> z{+O*{h;JG}4*+|#cAbHe@(r|Da<@9`>!(5$MfImrhtB|%{bAHkOo)WjGc?R~B4fu$Oul)u*&da|WY|Fd%u zahbQsQeU0K8k=u72ag(C0ogYS1xrIt5=HO-WCWhl2N_$mU_N6|hu_Z719Ok-7z*LT z>@K6EVrqKA#YWS@Vw`9L-s-SNPK-1LO$>pOBc4MUC5E3r&Ol05GA(w|^JZi~eKQ@u z1)Ral1v$2tnQ24dy!fr{+LrR|TML@sQ$*KGS#%E!^_`tE=+xap;&}uOQmitF8eCnA zF7;#Cp^aOIw&UqgaJ0gGD)Wned(#$P)4HC~U^m(LAQ~X7rxkM@Oipo6E7NYO?=&W$ zio-99ulS8|3)Vy94Lb@dj2lNaha^-RqCJvV=U13_u$^K$iBXMgej zkt$<4C-}x#JSk~u2YHMT8He$%U=&Mi;UKYf^+UaVo3|l@t2M5lpOmaiJU2G>5R5my z%Sp;}lfsAO8RDe(Q;zEhk|+V!AQxLN zCG{iV39u#2?Vs73@1v*B$9SsBXq)pXDh!IjBtaO6qyKaEb2Ui#O{v3ctM?|Xg}o{0 zKRTSPy#|^vc4VDyUT~;dTYLS=NOIg{Yi67}`%qzq5k;Y_+=oxYK@+h*rZ#LAo#!-N z9>!;Em@pa2ls*)4H}OzWd6MKjfRYLcBTR6skmy4y481%c1D&rXtX@3ko>oRD!1D(` zzAn37wAz8Cwwc*ueW@jF;hl}zH7nirI(hYwV}(oaUwEbIW}B6HZgN#?)zVipJwa+5 zlnfSrSGDv))yUKcF2HB{bU;t8wu~TzXn(Pdam)R#ktKi z4_B95Q(S*wySh+!WV`rlx|gG?Qx~NIu4j*~oCrNOtI0wl;*EG)wJJP1s%YdzSy1V< zk6g6Xgg5MKiC`r;NqiO(qCYBL!AEdXoFi<<-^P=N- zcjy=5+uaFq-6b$eo~CEoMcKD|jE_>gmC}0ec4W!LRNkr4_?t7cvoFYbYS<0GrI2T@ zt*#2Dkdm;QPVTtloI9I!eQEQFsxxlv)}^+C!OW$ad#P?rKEJ!MZO;*7jBE;o0OHc6 zgyZlPu|a<96^vL^HTat__1E3QD~$FM!=iYAQCoNoPv%~~8wcjj9s6ZK8{59D5YAMb zp(8Q|2b|j>-)t~2k^bb)s^YOvoJHLa9&gy+SujDO?PIse^Cszok85PYJx;glJZOBb zYI~b)cG-7ehq6sQzfG^_BblZLp-#Y7LUtU* zn50ZEY!fh4@$_L|+Pd2v4%eiMzkj2$=SZ9l)-L>c_9Uq%WxkgC&*{5XLUQX)v^Hjp zC%&>a?@#RAefDjmk+q|kM|839djsz?B#shVK0L^`#lN60F5eCr5jyw3;P+sC?%TLw zQV)xJEQ5|zKcoA(Z42xq3h1-PirI~aCy~1tR$QWy4t}qFD@?RGbG$8gE_I<|>P>cb zf8lu&6aGBWw2}V)CX~@QxRHCuE>DqNL>;Sx{2g@kZJRqCcGbk2Zb_&qRy=;UTW{UF zjwI|TB`K&W;DtMi%luPE_3YntKKm0`)5P#y$a_$~L7!wN1Opz}Fet%`idNV4gWH*J z*x_;>&l4 z9|)FV9a8hAxjjD3QoYfgwwqaNiYiL>LylL1+=7idI`^IxDC|77I6V5%taa?)rQ_^l zG!gsWIAc*Xf^|b)d`C;Zr=b3Yg$!*_ch3TiA}KqZCt4|&+yvuTBVcaZW2m+URY1H| z{dulY_t@hDE0>vH%spRJ9M70qH0T!+l?6xV4GFTk<9-ET8z35?yk&#vuThTE?$@`w z{S5K>cmV31%+F^+b@|_oz8>ZFcHFx6{-Xkys-e|o5;Y$;+PdY%MG&5dO!z0rs;pEX z=f?=ynSqyp?&%#!FW`9rk}k7|W102QZ)p{uK6MsG=NkSlW1{zPTw99Tm~`;wYUOud zar*g`92$LBHGq55i^u0DGmBoOrFEjBMlA>og@wkSP$c5a`+cpZ-!~vY3-)8kx|j{R zUY3+vRbz}5I{TB;KOA}GQ=855wd($#DXleQmZXR&&sI8s)X`AtfB}!Va?9A*VY>GM z(?62+c31CgfJWd&gZywB<4aSU`76FB5Jf~S`JVTUTyzuwb~Ov_Z;6ZF)5%1=K8yh( zSU*7{gi4-_$gTontDACGtzaTmiM zF>JFXn*?zcNXr#9!7UQZ) z$Uz7q>7C)C0BzuzSik+zu7Yx|%Q9DbBl@zCf|t2|Y6++xi4I6gPA<&PpV7v*mxUgI zCi&f+1?wi`+ou=g#zlowDp!PgCv@CBl&nnP_;9$V`9g8tfwL>vJ1{Qz$VI_o2$Yh_ zH*tssg<4DukuTQ~g_7f2e6WM>`1NM<*ZRvMhpDpzFFRgtp1t#Sw+C(WN@Vu2AebJ` zYO;R!EwnO%lj^{LL=!IyhGl*+d>e%UA%DdLsKRYji9NJ0KtCekMP-V!Jl`h{Ubg_M zZ(EE~Pc#JYHE6sV`sv0Q=568^^T>?}Q7$O|3dw}#2f&$+&kkd4JkEE=0oE5r>!x`a z=(v%8Yv7UNxV4Tk?f_^%-PE5x4vE1(LN`4D-o%esbVSBaik1wS7%?7yebT0J%6jG? z&9)%Fu~fe66y=@B8yt`GUVr$UE@~+8;9}3T)u}-2sL{D)=oF9w+<|f$ZGdMO zwT@bn*<%$^4X;!2+581Bg|5&4#Ra%~uhWo+yh{esz{@#CnA z$yh+n@uCDsKQQ32LmNl}y*H%V|M}^?q+7{4Hi8+~bR2ulKYka@3ebPmFIN3iOyS{5 z6O7)$Pb@i9*3;7i83lF`YNa4wU;1;-w!q%DY~Bo9;~;pAQiLbANg^;Xe`Cd6^k-i7 z{$_qX8A{jlNa7G{epPOG?s1AivdZ1?6c3zYNU+4omT)Bxigp;$iGM+ziE(cb!?KG% z^zo?#NQD9j`-Q9p%%6^`RvcC9(ps*KJs#h9yI2ytA{4usz|a3&lSW^mU|;nD2_M=j z_%Z%U0ongWYH*Tz=MqQaj~AvI>8jO(HUxvIcZ=l-N4C?F$xYxoJ(XSJ7`XK9`)xUQ zOL6lWcqK^l5CKUYA`r08AY$|m52-S&7n!B_AE5*8qL@71Hq8wQ27v$n5qUu8VdOTH zDX-?Oyz^J|!S4UUY6#+rk&&wZl7-x+-HHIwS>y!3dG`VS07_+5RklzF4CrEWw}}vS zqq||PbqVq|SJze0mCZHaSB_Bl4vb|Oc0T$W&<_<|c6A5jg6#?fjG?DHjqo_#woOaH z^%Ij}9Fj69<8)W{tEHBSziesP%T5Mo>m2-4* zkhGJN8+h#AwTn-*laRBP?E=XZU%x;of-?!c$4?-G1)iRVIfxKj`ALLj4x_3^A)R3@ zhw0G>z|1-z+kU4$6e0twoQl6UYeGjfFmy{rp*#M^I!1nuHw8})gm?5oTmsS|42FDr z$M)?E0zg%?^KB~1%U>Y5LxO@)KV0tbN=V_^0VM7E{BTT63|6VA)L*zX@Bt`ul{kAhnpMjoIv037dmg>M~_4i(4qdvdjvv@uy-q~lxXYpHlVi<1{FJ63H6X7 zz{w%7lhBkS081QJLc1@ZLu~oi3*>v8>TlvPNQjsB4<2E$^PIDzUDQh;`PJ)~6V!=1 z;mhA@q2}4S=;yCcINcB;_?W#+6t_X*^c?Fm{UIo=BhcSYhf-0 zERi&G%p^%85h`J@`M$^9JfwsP3+;8Y89E6o=12>e*DPy8P22GG;p4 z94&a|&3PFB5C6Yy%ZT?$&{6tV?BXm(zAYp3Fg6zMwQrL?M*0H!yGlJcHdakwY|{W! zc_pR!IyPX1i@t2l`pFO(AeGE+c5uFYnUZ=FFMv(cHB% zx-P$*JFpzX19|@bQ>sO?b;4NH;05JYWYm^0{aI0`-s@X!AFLl`0*c|SEWlG0#e_W1xbnK)A!^8aQ-bvP)F z`;8)njwMXo`P^54Y@x|W6l;+5vkUXd1$Bn<5XvTc?lyWqWN;~-ezxo zn03N`SHR#i#ohA+3D2S1Njgbc8@&UZj_?r4mT@4i@nCNs+q*FFCWx9-Bo1S-DBv$2 z^z=Gp9@KWvJ z`KM}g``=Y!ySkB9b|L0#u=d8F5__RgQrp9l0rRi1` z&@8b;@%Mt`cMHW@E(S+D?(i+$HF=ztd`ye&d+qxB2!(w^?uTgnlS^j2C6_DGd5Mb~ zy#nvH`PHSn=?BN;jMD5m>=`=`&a-{eeEqLw;wc2(!$Dzdo94ixK;MN?O)2B}WaffP zBCGE$x{OlX_x?R1Mv;SBFSgCx-pJQA7Hy*cW$I(8de(VL%(e{>$3F;#gyef_iEE2Q zRlvXJ$vfWX+G1N3&};U0L1nkOwviJTwl9+81eVd{~KQ|L>n`g>~e$R5bx@?j!%vC~o`T-lm@9 z|A(dU|Fa){vlEfbixQ;m29w2%2a1PF$a}Bq=yanp!b(N+zbywd_|h$~J;B4%q{o$4P%uB%s`#P-Mwa2)YAGrhF8d(;QyVavC$dQj$xv1k z-soeiaxiX%#Z7QzWJ=QrsMzN1nB0PDm9WW@_Gm=^g>X=8diO!^S5tD(`}YFnT!{2A z@uJ=N;GcQ~_u@9)yJ=veVduBE>nFwK5D-o?CFM){j6E3wsA{3XCST z#Y{GDeWVxW>pG|`M4R~nKWl>3veq9YW)cN+gEmYZoay+DToN`n{5p%cV@O{p${`98 z77$QNSIyLX|H!Q!m4IB6ts7sfNrMkxE0P8PB~iL3{Mu3Mre>B1A%7$!#A}TRl4UQz zK+00@gu;3rC#sr#S-?>m|81K$$v2HZM#_mVhQJ}LQ`{!FyIz!j&%ypPQ%yMTN2v_6 z*r=${u`xMP49_@)sjL|p3NkW!_d~Qe!ex`Fd_OfbWF;nk0i$^j( zZh`ms>z8`=4CX!9KZGHfAzlvQr&1qRin71(E1n4)7_isQPjAeW>v4^D<^$sRi3Tdv zRg^YZLC7R1#ex4gz)1&>9?5f#hPJAz6zN&3UXsF}=v&_6qBF}a{~Q&idz8voi{lt* zh0c+erAYIkP(Od3gfPB21WQ87kE(SU$7%erg`gZmE(i6wvX+*`>Ph5>%PT9$WF{vq zSFhk)zH%I+vG}hO9y(r>9v&O$%Vw#=kuw^Z*VCti0Bc1zc9}QyrHP`%!v^pR2(W0> zDOvq3SFF>MsQr!-WEn-w=PL9&c0pG5D|YK*#?MPwkHoi>q&kYPB1Hml=&JVN*i%`| z8z^6Qh4daXe(}h}WiSo{Yib?z4A?>OyTVU{=)9vFjRXk8Ti`U}C=B!8vtaD4WGf^C zK!LYsn7=x4VPN1%TpT7mv(fl79z19kCIa}<%N?w z*Ev#DkeddoQS8}+C4_AUE)!mph=?l|h;wlX(zLuh^(19eUWP378V*EJ5Js!kW56+B za&I=v!L^K2M(Jc4Hzli_yq4O$`7U&fW4Jq%6F9GfrlZ~mSP?GGIysT7Hw?^joZ$%s z2;t0%+w&3l@Z&kYzEo(!LRj@7T;rWk;eHJ^*4JFsW?13rz_(&)l8B@%F)0bKP#pD6 zNpvt*W&xK>O-|OW_rPdU0HZHJp%R<>es%l>5^k+#z$J&O!Brdl+&}gJKWXIoNK122m8Ds>M7%6xuHp@18Gv zS;K&7FOC6$`;p!dj&=f;5F}OQ6~kGH?O2j2Zxm_=VgOccZ6GDcMb}R5Uy;tbZ{`(@ z)E7QcZ-&dN25nH3*?&?>fCHim#vdL#dK7A%*0gG_0EOfgR2u|ME*TD#=Bb-?=pZ zkd;N^a0npD*t2)oV77$95us*WNt{M_H)j9BaSOZwNhR<|uzI0BMLCWCMJmQCj~Q;~ zS*cQpY6&kEJ-bS-%dix^pMhmk%<_alA2fC|r7f>vKn@VSaPEsvIj7WR`fkX1omZS}P2E zFWlJERSU6FkXNAifsrT_VqhnteUG^l92njXe84LhZj#5JegzW?sSm7}h0mTO2lrrP-c z3|LGc##yYU)*603fNzR0E$YGX!9d}S9y6FZS%G+jNF|__gOdlI7+~&Kx2dz@<9l&f zFa)w4Ia1!$rOgozMP4pq6ly?MDJgGw?#(z76)Yz_L5N`tc=O8CgV6LIJa}1&I@-bv z)6BCgdC6EleE0xV1f8n^ByZp*9SN-p$aGCKT}Cznby7pa8GimS%HQ9wDxx;hU<<|Q zCxoYc;@kHyxxy54euv+4xP2gFK&oV6VX=MpK^amU@8=)~y>graNJhO6yirir@eRl2 z-0pey($t=-1T9wByI|@#)`Cs`YX0yup54c>O3^=old-LXLy(`}VK2e6XS0&m;1r)# zjnZssc^OC~8d+bvyF~$D=y8dNyfT76U3+sgADrFA#NrrFfMSZ@iRd2}9eu#13W`wl zQgA>V_L7j2I!WzEtK--QBnH(D!abjlIT;I<1&qwl!~p@EueJDf^QaJKF%0B{fMX!k zV!qLjV~N=5hv}}HT4S~QT;OG9G zlJ@qw;t7rcb|2dOIZFgFO93A>qb-xY03Ij&r7gM&o=%BJol8<4nV6`3q<{X%++^2^ zKj(U8v2c*T>DrbZ?#k^=?;?0jdqQb$`N^Jma`ZiRW*#l=({tuMUy502CBw8df80Ew zk4*#g*2UFzrmc5Qx zz3^W{PLL=ReEXV`k~NM+TwaKFs2jVOSP!)9SeYxu5A=>1M^kgzGL+ePx~)lifJmHtL|Ih$KryeUU7#WBQTuYH_VPTA>MJ&19geQcjI zA(?!Ga$<6f)c*a@G3;45@%P^Xrvbm>Y!LP^ z@)V=ZQBfFjSKU-X#T5rg7=0rcUzIdn9V9RZlEoiEZ=Miv14-GQi*Gdl7TYB5T){DO zjH{ml;#SE@ihrR`q2fbQwy{I#u=8H6n(ocIPm7b@zO_My>o%){Zw*1(2emd%7@&v9 z)!^59g)u}=Gwa3!>`d4Qr0kaHg|z+)_9iekgeIh>qgGq@`;-&Z{Xi+CZSWXB#!A!k z6KFc_5{D%MY-VO=ve3Z~=ue&5w=WcTuFUvQ&;0i79{ACrrB8U6b*&d)uxXKo+t=Xe zXcX!I9D*7eNUkYfAEB~9-VCq_K4L064o}0y2*)s?0?yE`?z4KeTlxyP#=02yas2Px znumUV8pY0h&3nmSBQoOv!)_{aS-@;sWGyL}ggF|&RUIb@5IwkQ^>VutF33RU2xn2; z64t)k?89v`b;~k1WbfYHbb)Y_AS}UTW&HvJlZ1|Mf{`OLOgr%v5g}v8zBvtZGr-$t zWlhA43B2)X*TzhHq!O@8L&<|tx8MgzOG+lae5uU%#fUYJeONx?O_b@x-+^JKkX=xNwnDYlft_TE9XO#SC z*`t4|L>sRM%VkW}0v%!Jo;`RLKAB&cfZxGr;v=&h<}QEv@`ac^p;H73@DTd&IOx&o z?Gf0#wd6iFaKnhLynHPJLglAVhrDnBI5L0^pyfXM`!^ON>N@4CS5qFTTp1Z1J?w?M z$AAu`VW2y_di1adL?C4Kc>PYW`{3iVBaHjE@$e9%lVoq~6GT}Dvq8+lWR-(Bh=r50 z{zlfcC3s~B%&2fr?7X5U;`~PjX#u=@#l>$RgFCo8IU(VKg2E({IYUN-HdHcK=@QRJ z3tHbm$|C*+%-Z&L4GivqV<8q)8Ls^(D=Xn}7`BRf7N^4}-Dl8RKYscY?&%xuo6g&` ztYACX+S$Pdiu4iSK;Jn3|lZYJBXq8FbaJSS0Z~wp#0U<$PilU>K;`O{uJj3H^(Fb zv*wd;qY4XMEG*b1&+H69WFovcS^i*f%C233$cDVG0Bw$pgjI@g#y&>IiII^@H=nEq z)*6Mjjv8Rw;Z=ay!o|h)3wC0FRF}E=KjZ+?!4rW_1S7tGK1NaA-Ju5N7jh`KQj&Ph z>;)JbYZW^;fBP1Eh!pcX{~GB_P)a~Wgc%ut2dwy9Z_D3|zXv1JGVqdPI{lLO9fl|B z%fC+GTG(rtSZHX-nxy}`5Vpw?(a|`YfGpczJBEW4%~!6o83zy%-~oczjyDXw2Vjtg zK|z(Ms=Q#MhN{+OZP`vsSyz{nh2?_wn|leMUwr-QcZd|@#u1hc-ka9EMY)J}h_*(+2`^1|)?5!J(PU&dp8rLFFftUY0r=8yn^u zYs1TBz4T&o6VmUQ24uQ$*+zoxR!Lf-+r5KQ96Js%->@JyG!#>!&ms{+Bt{-9z|XII z;Mw^IY%{}!ZyM9!QEc}%+P9)cRK@=F(byO_^8y}lp#S=HCCC^s)h@m968C@iQtuM}pBZftB6NS_DjEKuLlJ zJd9=#SW9P}4M-)G{5!RT7B=O%X~z&W%uP^>4j-6&C0S9hEnh5Z{ujledV`&O^uD4Fao z_NRn*4{Y_~pqIh1C2j(p5L%Le16ML4>F*7UYoaEb?w0aU#>hYb5|rY&dcb{dRIPgu z{)YfIfx8c%P4B)@!U**UC+8F%jbnIupNYA7oQTuo_E(EqsNx?#R>p|>ZcJ~9K|kX5 z1DLU6$^{N07<6u|L$XY_jl|N14pvK0qJd|RX)}^cxJ@+ly0Q#*To+GnN{Aho!z03; z`CWJA0x4D@qo`}d>)@>lNM~(qxX)fUgGLg)JbcKv#zt-~E_EE698*S)x>LB5Q>Y~2 zO^aiq|HHcW8SguONG}eNT#~q;!o!1=fE+IdcZ5+T%j_bXuqbI57-SXhV)PX=ugN!z zjlkgq+uRv9ieLNDDTLuL;3btEAEyAdzQG9XqFO_4L_pzd(-`WMn+t5^^LzdHPy}j- zRS$XLTxtf!qO5$Fg#|-fu55;wHrq>JXFD8KYi+yTzBH!E-XbU$VuU73{MJNB+9bx zYd|edq9wieh!iYU(ArJrJVGt8vC^}F(+H_jwI0{K`}g;X!(U~9w+6#Q)HO7IYFd3m z8guQ+6^xzJRy>K+^ZR!d7~-PZa-S-5C&59B34~4<`q0gXDMb@c;pEPXgUa6C{r3Qw zC5#NrMb-Y|VD#$k>V4OZI_4&(oR>k4=tbs&2CAo5dtSH|IQ zNDuh{$pux~SP8};Z9wh}?-!t%p$@lrc3!ZVPX|+Cb#2W_4lo1;Az1G_UgJMPhJz4p z^tv?-}0=#Fp!SQm99z%&Ooy~7qS%;3xUJj%|atJVuJ20y;N0hv(G!9TsXOJgPItD zD$37~U;?s4F1Br~FA!6qF-A7$suQT7AdX@D71Qq-L~b7dQG4TifqP&O?O_KD=Yn49 z)X9_RF)Z1C+{$WP+>0=R0|iTIK*J;c0J=*n1HE6t0>WvA@fwh`K^<1Y?0F&&r<9L$ z8mCqs7Droi^L|BAG3%dR7&h44Fq4Dj4@C#!Iz~|a%;7>Q9tsB672BlzeERpF9c}>Z z1E4=Kkq*QP-KiE+3ybfqty3Lz+b-i7<8i?YJ>Rbzfe*FFv^Gt6HPS~{bkvg0?DR%c z1H%?EciG8l3EIS`)q`PApTanc|M=~kIeLJghTq}k?Ff*feQKbA-X?{&j zRrTXzU)=%t|6wKx-YSydU$(E()8*CF7SQv2vi0*uo>oRq&Kw-(rYDhVOz!}YhQKic zcn)n0VT>WT|KU)yz24F6dNT_PUVeTy=H>3rP7%0gVI3fTIXOH3OeVXlpw3QnyGhN> z4eVQ2eSH@3S5P@)0`Wrf?H_M32AZA)u1t|g8n05PokvWhqNUxydPFr|hS^6>Xj>Rk zy~NDL`3X(0E8wa?h2i9bc4pPEKt^zk+ji83{{C2euzv>N&DGpTnhRS+;GcjVlM)lZ zAg%k|@EnOO_n9+G-HM+nwXkB~Add2J4Zt%jVP|eUgX!5|?0vGJ!X;%eyljPHwT`2t zK7n2W_8d(9y)G!l@nY*@lk-H@AgxE0DdM_#<>JNrBF-4gh;Y2y2cGU|Yds4NhEqOl zb0zf4?qS({`S@|O=v`f(>Ol-&!!QO+b=l;Q1HexE?+nr3fdAnhiD@dkn$Otpc$_^6 za{+`-oaLz31=!eLHa(_~9~O08d;@7B3iGx$_1!+Re@3o~>|6=ebDOq&^TPuDs7sfs zki;`(2$4JAfK~;Q1wNY6pJgGj-S&PAquCfm9D~dI(Bk|p%A1We`4Fkdt;52?2lgy^ zrY8(%X1McjhC^pun|q6+OQ? zEMJF%>k%dnfsC%0;WV?p=7RB~@TEiI+p8J_AbAkPDW?drdpH4wVoP9DNVj>FnErug zqx2-)=}=1`=mJMYx}=0E9pS&au5OZTD)ZH=Z_Uk&kY$1l#xgcR_zmK$fl>3+4KE;@ z)(#Gp8`FfZIdTQjjp52YNMVIhe?W>7t?W zzlrqJ$Ovj`VmxKH^kz>*A)uqdEEf^*+M5mEqFwZDv5V~6uk1mVRIN3aQi zqEcN~cqED-*U;E_m|0|J!3=t$cu4?Wj(8DPh7}dSTVCy!J(QE1i_SCfqW%XOl;Q|2 ztql#Pw{BGwV(KjmOCRoq%Wf@OojnXNi93a!8W4vMg;Cqf5J6ygFf)%c45&&^t*$L% zJZKN#SZ&K-e9t^{)$G=-r@_Hx9e~IIo#Fi@@E-mEd2$~56V}!<#2HsvnW>R8inI`T z(JPFI!;;2|!@>Ivh9#KD5aP2uw^Hiy2ALo5FfLx+#N$#I9;2-ck{W#f5Jm7#a2BAf z@_38c<&*twTm2&<2r?l~ObH1It17_VPoF#iw&sFP5mJlYKK*@tNXaQg-ZR?1fM&V8 zkAg`gFIouk3(g~MG>_vWfE2^I0PrjnsJ~%mh*=6CTcM}s@cQ$OEEqN*pT*qDu&5|m zcav?~n}4wI!K48r6j21y?%jJKxe0<&uvBM02~6(?jdwc`R1d|dXoOMfI$?;(0s z9lLCm--)~$#Bm%2kd5^J=#4+7&fXH|u})7%_pmZqx5%*p0K^+NH%Iv?@u_GDR|stwj>0iISyg zRT&IgM~$^iOfu1kX|Y7bR5zv?Dp?|m5?YAR@O^&F z8(%2>s229<%2(t{GE)EYrmZ zUY^m76Mc7h$XmYtM5D~_g@w!WedW|$KTyC^dJ#8pO?Xfn4CC~KJqVVXn%3RFAHg*U z-V&~DYC2NgyLTxe7%r`)d=kRnPz8laUKf9+>)*#G9|=F+jjRpt`pq|Tc5U#CAmT99 zh!+4Fswl<~Qi%%lDgUjp_ox_m%?DMlTzQtW84&lv(;?o^e_TYC*VZ|HO# z$M{K`R-9i!NHO%a?Tl+O8-s9%qkK`aG=~(U7cu&$MN?f(?J&0`-i?yit64dT$vnbR zL}I>Rax7}$8B@)*^w%@cXQ+|Z!L&3p?<*o41G+A0AUJ%ulEw7SqbOxiEUPEKz4bVx zm?#pawJF{WOVGQy7HIKc$Cs%!;yN^*Z1nx+V77%=Sz2OECD-0;4rXYB5i@`|GXS

aF=T6zyLf78Z|tjr04KA=W|-Mn8CX=S(bdMj%_ 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 M?>hUmoprNcl3M3hdE?vj#55RmRv1eH$dhHqbH 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 literal 57570 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 C5{_8_ diff --git a/docs/src/figures/manifest.toml b/docs/src/figures/manifest.toml index 2ad9ef5dc..af3425323 100644 --- a/docs/src/figures/manifest.toml +++ b/docs/src/figures/manifest.toml @@ -25,8 +25,8 @@ depends = ["src/InnerLayer/GGJ/Ray.jl", "src/InnerLayer/GGJ/Galerkin.jl", "src/I script = "make_backend_regime_map.jl" [inner_layer.convergence_Sinvariance] -commit = "3a0837e3-dirty" -date = "2026-07-08" +commit = "20887ed8c-dirty" +date = "2026-10-16" depends = ["src/InnerLayer/GGJ/Ray.jl"] script = "make_convergence_Sinvariance.jl" @@ -37,7 +37,7 @@ depends = ["src/InnerLayer/GGJ/Ray.jl"] script = "make_rotated_ray_contour.jl" [inner_layer.solution_profiles] -commit = "3a0837e3-dirty" -date = "2026-07-08" -depends = ["src/InnerLayer/GGJ/Ray.jl", "src/InnerLayer/GGJ/RayAsymptotics.jl", "src/InnerLayer/GGJ/InnerAsymptotics.jl"] +commit = "20887ed8c-dirty" +date = "2026-10-16" +depends = ["src/InnerLayer/GGJ/Ray.jl", "src/InnerLayer/GGJ/InnerAsymptotics.jl"] script = "make_solution_profiles.jl" diff --git a/docs/src/inner_layer.md b/docs/src/inner_layer.md index 7ddfecb95..202c56c10 100644 --- a/docs/src/inner_layer.md +++ b/docs/src/inner_layer.md @@ -111,7 +111,7 @@ The `GGJ` model exposes three solvers through the `solver` type parameter of |:--------|:-------|:--------------| | `:shooting` | backward stable shoot from ``X_\mathrm{max}\to 0`` | ``\lvert Q\rvert \ll 1`` | | `:galerkin` | Hermite-cubic finite-element (real axis) | drift onset ``\lvert Q\rvert \sim 1``; 1% error by ``\lvert Q\rvert \sim 4`` | -| `:ray` (default) | rotated-contour spectral-element collocation | ``\lvert Q\rvert \sim 500`` on/near the imaginary axis | +| `:ray` (default) | rotated contour: inward-marched far-field condition + Hermite-cubic BVP | ``\lvert Q\rvert \sim 500`` on/near the imaginary axis | The difficulty is the large-``|Q|`` imaginary-``Q`` axis itself, where rotation and resistivity scans live: there the layer's pseudo-resonance at @@ -163,38 +163,34 @@ contour lifts it off that point; ``\theta = 0`` recovers a real-axis solve. ![The rotated integration ray in the complex layer-coordinate plane at Q = 500i. The real-axis contour runs through the pseudo-resonance x² = −Q²(G+KF); the ray at θ = arg(Q)/4 = 22.5° clears it.](figures/inner_layer/rotated_ray_contour.png) -### Spectral-element collocation BVP +### Hermite-Galerkin BVP -On ``[0, s_m]`` the system is discretized by a **global Chebyshev -spectral-element collocation** boundary-value problem: right-biased (Radau-like) -collocation at the Chebyshev–Lobatto nodes of each cell, three parity conditions -at the ordinary-point origin ``s = 0``, and six matching conditions at the outer -edge, +On ``[0, s_m]`` the system is solved with the same Hermite-cubic Galerkin assembly +as the `:galerkin` backend (GWP2016 Eq. 32), written on the ray +(``A u_{ss} + e^{i\theta}B u_s + e^{2i\theta}C u = 0``), with the stock parity +conditions at the ordinary-point origin ``s = 0``. Instead of resonant and extension +cells, the far end carries the point condition ```math -v(S) - \Delta\, U_b - c_1 E_1 - c_2 E_2 = U_s , +v(s_m) = U_s + \Delta\, U_b + c_1 E_1 + c_2 E_2 , ``` with the matching datum ``\Delta`` and the two decaying-mode amplitudes -``c_1, c_2`` carried as **bordered unknowns**. Here ``U_s, U_b`` are the small -and large power-like solutions and ``E_{1,2}`` the forward-decaying exponential -pair. No quantity is ever propagated across the layer, so the exponential -dichotomy that limits the shooting backend never enters; the boundary condition -splits it exactly. - -The two parities differ only in their three ``s=0`` rows, i.e. by a rank-3 -update, so both are obtained from a **single sparse LU factorization** plus a -Woodbury correction (the `GGJ` internal `_solve_parities`) rather than two -factorizations. A residual-driven bisection refinement adds cells until the -collocation residual meets tolerance, with a roundoff-plateau guard. +``c_1, c_2`` replacing the last node's six Hermite unknowns. Here ``U_s, U_b`` are the +small and large power-like solutions and ``E_{1,2}`` the forward-decaying exponential +pair, all transported from the series radius by the march below. No quantity is ever +propagated across the layer, so the exponential dichotomy that limits the shooting +backend never enters; the boundary condition splits it exactly. The grid resolves the +full local WKB rate in every cell, with a minimum cell count for small ``|Q|`` +(the `GGJ` internal `ray_breaks`). ### Far-field boundary and the inward march The large-``x`` boundary data use the **same** `inps` Wasow asymptotic basis as -the other backends (GW2020 Eqs. 3–52), evaluated at complex ``x`` by -`RayAsymptotics.jl` and applied at the series radius ``S`` where the series is +the other backends (GW2020 Eqs. 3–52), evaluated at complex ``x`` and applied at +the series radius ``S`` where the series is trusted (residual below tolerance; [`pick_smax`](@ref InnerLayer.pick_smax)). For large ``|Q|`` the -trusted radius ``S`` can be far outside the collocation domain ``s_m``, so the +trusted radius ``S`` can be far outside the BVP domain ``s_m``, so the power-pair data are transported inward from ``S`` to ``s_m`` by an **L-stable 2-stage Radau IIA march** in the quotient modulo the decaying exponential pair — the subspace in which ``\Delta`` is defined (the `GGJ` internal @@ -209,12 +205,12 @@ error of the ill-conditioned implicit solves into ``\Delta``-mixing of order ``10^{-4}`` at ``|Q| = 500`` in `Float64`; extended precision removes this floor, while the well-conditioned resolved band stays in `Float64`. -The result is a seamless numeric↔asymptotic solution: the collocation solution +The result is a seamless numeric↔asymptotic solution: the BVP solution on ``[0, s_m]`` and the analytic ``u_\mathrm{small} + \Delta\,u_\mathrm{big}`` representation for ``s \ge S`` share the same power-law tail — the overlap the outer-region matching relies on. -![Inner-layer fields Ψ, Ξ, Υ on the rotated ray for the q=4 surface at Q = 2i. The collocation solution (solid) joins the asymptotic representation (dashed) seamlessly at the match point S = s_m.](figures/inner_layer/solution_profiles.png) +![Inner-layer fields Ψ, Ξ, Υ on the rotated ray for the q=4 surface at Q = 2i. The BVP solution (solid) joins the asymptotic representation (dashed) seamlessly at the match point S = s_m.](figures/inner_layer/solution_profiles.png) ## Validation and benchmarks @@ -254,7 +250,7 @@ machines/BLAS builds the absolute values reproduce to ``\sim 10^{-5}`` relative (the damped-zone implicit solves carry platform-dependent structured roundoff), which is why the table above quotes five significant figures. -![Relative change of Δ at Q = 500i under independent perturbations of each numerical knob (contour angle, spectral order, series order/radius, refinement depth, march tolerance, handoff radius, purification depth). The worst-case spread is the reported error bar.](figures/inner_layer/convergence_Sinvariance.png) +![Relative change of Δ at Q = 500i under independent perturbations of each numerical knob (contour angle, mesh resolution, series order/radius, march tolerance, handoff radius, purification depth). The worst-case spread is the reported error bar.](figures/inner_layer/convergence_Sinvariance.png) ## Choosing a backend @@ -273,9 +269,9 @@ p = q4_surface_benchmark() # GGJParameters for the q=4 benchmark surfac Δ = solve_inner(GGJModel(), p, γ) # (Δ_odd, Δ_even) with the default :ray backend -# Full result (raw Δ, contour, mesh, nodal solution, residuals) via solve_ray: +# Full result (raw Δ, contour, mesh, nodal solution, boundary conditioning) via solve_ray: res = solve_ray(p, GGJ.inner_Q(p, γ)) -res.Δ, res.resid, res.bc_cond +res.Δ, res.breaks, res.bc_cond ``` ## API Reference diff --git a/regression-harness/cases/ggj_reference.toml b/regression-harness/cases/ggj_reference.toml index b35ca20a7..d6c863ea0 100644 --- a/regression-harness/cases/ggj_reference.toml +++ b/regression-harness/cases/ggj_reference.toml @@ -4,10 +4,10 @@ # HDF5 path in the computed output, how to extract it, and the noise floor for diffs. [case] name = "ggj_reference" -description = "GGJ inner-layer Galerkin solver, Glasser & Wang 2020 Eq. 55, γ = 1+i" +description = "GGJ inner-layer Galerkin solver, Glasser & Wang 2020 Eq. 55 with physical τ_A, τ_R, 1 kHz rotation (Q ≈ 0.22i)" kind = "computed" -# Δ_odd / Δ_even from solve_inner(GGJModel(:galerkin), glasser_wang_2020_eq55(), 1+1im) +# Δ_odd / Δ_even from solve_inner(GGJModel(:galerkin), glasser_wang_2020_eq55(; taua=2.11226e-7, taur=0.968219), 2πi·10³) [quantities.delta_odd_real] h5path = "ggj/delta_odd_real" type = "real_scalar" diff --git a/regression-harness/src/runner.jl b/regression-harness/src/runner.jl index bd4a10617..19cfc19e0 100644 --- a/regression-harness/src/runner.jl +++ b/regression-harness/src/runner.jl @@ -98,8 +98,10 @@ elapsed = time() - t_start """ # Self-contained computation for the GGJ inner-layer reference benchmark. -# Runs the Galerkin solver on the Glasser & Wang 2020 Eq. 55 parameter set -# at γ = 1 + i and writes (Δ_odd, Δ_even) into a small HDF5 file at ARGS[1]. +# Runs the Galerkin solver on the Glasser & Wang 2020 Eq. 55 coefficients with physical +# time scales (the q = 4 benchmark surface's τ_A, τ_R) at a 1 kHz rotation, γ = 2πi·10³ s⁻¹ +# (Q ≈ 0.22i, where the stock Galerkin matching is accurate), and writes (Δ_odd, Δ_even) +# into a small HDF5 file at ARGS[1]. # Runtime and environment are written to ARGS[2] by the shared run-info epilogue. # `solve_inner` returns the named-field `InnerLayerResponse`; the historical # delta_odd / delta_even slots map to interchange / tearing respectively, which @@ -110,8 +112,8 @@ using Pkg using GeneralizedPerturbedEquilibrium using GeneralizedPerturbedEquilibrium.InnerLayer using HDF5 -γ = ComplexF64(1.0, 1.0) -p = glasser_wang_2020_eq55() +γ = 2π * 1e3 * im +p = glasser_wang_2020_eq55(; taua=2.11226e-7, taur=0.968219) t_start = time() Δ = solve_inner(GGJModel(solver=:galerkin), p, γ) elapsed = time() - t_start diff --git a/src/ForceFreeStates/CoreTypes.jl b/src/ForceFreeStates/CoreTypes.jl index c321fa98f..4d87f87a0 100644 --- a/src/ForceFreeStates/CoreTypes.jl +++ b/src/ForceFreeStates/CoreTypes.jl @@ -205,7 +205,7 @@ gpec.toml. # --- DRIVEN (RPEC) outer↔inner asymptotic matching (rmatch match_rpec port) --- gal_match_flag::Bool = false # enable the RPEC inner-layer matching: solve the coil-driven matched ξ(ψ) from the gal Δ′ + the inner-layer Δ(Q). Requires gal_rpec_flag=true. gal_ideal_flag::Bool = false # within the match, build the IDEAL solution: skip the inner-layer Δ, use bare coil columns (cout=0). Mirrors Fortran rmatch coil%ideal_flag (the EL reference). eta/rho/rotation ignored. - gal_inner_solver::String = "ray" # inner-layer Δ backend for the match: "ray" (rotated-contour collocation, certified Δ at the optimal θ = arg(Q)/4; robust for |Q| ≳ 1) or "galerkin" (Hermite-cubic inps; drifts for |Q| ≳ 1) + gal_inner_solver::String = "ray" # inner-layer Δ backend for the match: "ray" (rotated contour + inward march, certified Δ at the optimal θ = arg(Q)/4; robust for |Q| ≳ 1) or "galerkin" (Hermite-cubic inps; drifts for |Q| ≳ 1) # --- Inner-layer "galerkin" backend overrides (gal_inner_solver = "galerkin"; unset keeps the backend default) --- gal_inner_xfac::Union{Nothing,Float64} = nothing # asymptotic-matching radius multiplier gal_inner_nx::Union{Nothing,Int} = nothing # inner-layer grid cells diff --git a/src/InnerLayer/GGJ/GGJ.jl b/src/InnerLayer/GGJ/GGJ.jl index cdd6e37d6..8bd0488f5 100644 --- a/src/InnerLayer/GGJ/GGJ.jl +++ b/src/InnerLayer/GGJ/GGJ.jl @@ -6,9 +6,10 @@ # # - `:shooting` – stable backward shoot from X_max → 0; # numerically stable only for |Q| ≪ 1, should not be used -# - `:galerkin` – Hermite-cubic finite element method; -# real-axis method, degrades for |Q| ≳ 1 off the real axis -# - `:ray` – rotated-contour spectral-element collocation (Ray.jl); +# - `:galerkin` – Hermite-cubic finite element method with resonant/extension +# matching cells (GWP2016 Sec. III); degrades for |Q| ≳ 1 +# - `:ray` – rotated-contour solve (Ray.jl): far-field series + inward march, +# and the same Hermite assembly with a point far-field condition; # robust to |Q| ~ 500 on/near the imaginary axis # # They return the parity-projected matching data @@ -47,10 +48,10 @@ import ..solve_inner, ..solve_inner_profile GGJModel(; solver=:ray, options...) Glasser–Greene–Johnson resistive inner-layer model. `S` selects the solver -backend: `:ray` (default; robust at large |Q| on/near the imaginary axis), -`:galerkin` (real-axis Hermite FEM; degrades for |Q| ≳ 1), or `:shooting` -(|Q| ≪ 1 only). Backend keywords given at construction, e.g. -`GGJModel(; solver=:galerkin, nx=1280)`, apply to every solve. +backend: `:ray` (default; rotated contour with an inward-marched far-field condition, +robust at large |Q|), `:galerkin` (real-axis Hermite FEM with resonant/extension matching +cells; degrades for |Q| ≳ 1), or `:shooting` (|Q| ≪ 1 only). Backend keywords given at +construction, e.g. `GGJModel(; solver=:galerkin, nx=1280)`, apply to every solve. ## Fields @@ -76,7 +77,6 @@ end include("GGJParameters.jl") include("InnerAsymptotics.jl") -include("RayAsymptotics.jl") include("Reference.jl") include("Shooting.jl") include("Galerkin.jl") diff --git a/src/InnerLayer/GGJ/Galerkin.jl b/src/InnerLayer/GGJ/Galerkin.jl index a6c287438..8fd490ee5 100644 --- a/src/InnerLayer/GGJ/Galerkin.jl +++ b/src/InnerLayer/GGJ/Galerkin.jl @@ -37,29 +37,6 @@ using QuadGK: quadgk # Physical-variable helpers. # ----------------------------------------------------------------------- -""" -Convert the inps 6×2 output U_inps (the Wasow asymptotic basis U = TPQSY of -GW2020 Eq. 53) at coordinate `x` to the physical (Ψ, Ξ, Υ) and (Ψ', Ξ', Υ') -representation. The 6-component first-order state packs -(Ψ, Ξ, Υ, Ψ', Ξ', Υ') with the GW2020 Eq. (2) scaling 𝚿 ≡ (xΨ, Ξ, Υ), hence -the /x and ·x factors below. Returns `(ua, dua)` each 3×2 complex, where columns -are the two power-like (Mercier) solutions and rows are the components (Ψ, Ξ, Υ). -""" -function _physical_ua_dua(cache::InnerAsymptoticsCache, x::Real) - U, dU = evaluate_asymptotics(cache, x; derivative=true, apply_T=true) - ua = zeros(ComplexF64, 3, 2) - dua = zeros(ComplexF64, 3, 2) - @inbounds for j in 1:2 - ua[1, j] = U[1, j] / x - ua[2, j] = U[2, j] - ua[3, j] = U[3, j] - dua[1, j] = U[4, j] - U[1, j] / (x * x) - dua[2, j] = U[5, j] * x - dua[3, j] = U[6, j] * x - end - return ua, dua -end - """ Build the (I, U, V) coefficient matrices of the second-order system `I·u'' − V·u' − U·u = 0` for u = (Ψ, Ξ, Υ) at coordinate `x`. @@ -79,7 +56,7 @@ row 2 (Ξ): Q² Ξ_xx − Q x² Ξ + Q x Ψ + (E+F) Υ + H Ψ_x = 0 row 3 (Υ): Q Υ_xx − x² Υ + x Ψ + Q²[G(Ξ−Υ) − K(E Ξ + F Υ + H Ψ_x)] = 0 ⇒ I=(0,0,Q) V=(K Q² H,0,0) U=(−x, −Q²(G−KE), x²+Q²(G+KF)) """ -function _physical_uv(params::GGJParameters, Q::ComplexF64, x::Real) +function _physical_uv(params::GGJParameters, Q::ComplexF64, x::Number) e = ComplexF64(params.E) f = ComplexF64(params.F) h = ComplexF64(params.H) @@ -299,8 +276,6 @@ end function _build_grid_and_workspace(nx::Int, xmax::Float64, dx1::Float64, dx2::Float64, pfac::Float64, cutoff::Int, nq::Int) - mpert = 3 - np = 3 side = pfac < 1 ? "left" : "right" # Cell types @@ -332,6 +307,18 @@ function _build_grid_and_workspace(nx::Int, xmax::Float64, dx1::Float64, dx2::Fl x_nodes[1] = 0.0 x_nodes[ixmax+1] = x1_packed + return _galerkin_workspace(x_nodes, etypes) +end + +# Cells, local-to-global Hermite DOF maps, bandwidth and buffers for given nodes and cell types. +# The stock layout ends in an EXT/RES pair; an all-CT_NONE layout is the plain Hermite grid +# used with an external far-field condition (`_assemble_and_solve_point!`). +function _galerkin_workspace(x_nodes::Vector{Float64}, etypes::Vector{CellType}) + mpert = 3 + np = 3 + nx = length(etypes) + has_res = etypes[end] == CT_RES + # Build cells and local-to-global mapping cells = Vector{GalerkinCell}(undef, nx) imap = 1 @@ -385,13 +372,15 @@ function _build_grid_and_workspace(nx::Int, xmax::Float64, dx1::Float64, dx2::Fl end # Set resonant cell mapping: shares emap with ext cell - ext_cell = cells[nx-1] - emap_vals = ext_cell.emap - res_map = reshape(copy(emap_vals), mpert, 1) - cells[nx] = GalerkinCell(CT_RES, x_nodes[nx], x_nodes[nx+1], x_nodes[nx+1], - -1, res_map, copy(emap_vals)) + if has_res + ext_cell = cells[nx-1] + emap_vals = ext_cell.emap + res_map = reshape(copy(emap_vals), mpert, 1) + cells[nx] = GalerkinCell(CT_RES, x_nodes[nx], x_nodes[nx+1], x_nodes[nx+1], + -1, res_map, copy(emap_vals)) + end - ndim = imap # noexp → ndim = imap (only emap[1] ≤ ndim) + ndim = has_res ? imap : imap - 1 # noexp → ndim = imap (only emap[1] ≤ ndim); plain grid: Hermite DOFs only # Bandwidth kl = mpert * (np + 1) + 1 - 1 # resonant method with noexp; +1-1 kept for indexing agreement @@ -427,7 +416,7 @@ end function _gauss_quad!(cell_mat::Array{ComplexF64,4}, cell::GalerkinCell, quad_nodes::Vector{Float64}, quad_weights::Vector{Float64}, - params::GGJParameters, Q::ComplexF64) + params::GGJParameters, Q::ComplexF64; θ::Float64=0.0) np_cell = cell.np nq = length(quad_nodes) x0 = (cell.x_right + cell.x_left) / 2 @@ -437,7 +426,13 @@ function _gauss_quad!(cell_mat::Array{ComplexF64,4}, cell::GalerkinCell, @inbounds for iq in 1:nq x = x0 + dx * quad_nodes[iq] w = dx * quad_weights[iq] - Imat, Umat, Vmat = _physical_uv(params, Q, x) + if iszero(θ) + Imat, Umat, Vmat = _physical_uv(params, Q, x) + else + # Rotated contour x = e^{iθ}s: d/dx = e^{-iθ} d/ds; times e^{2iθ}, I is unchanged, V gains e^{iθ}, U gains e^{2iθ}. + Imat, U0, V0 = _physical_uv(params, Q, cis(θ) * x) + Umat, Vmat = cis(2θ) * U0, cis(θ) * V0 + end pb, qb = _hermite(x, cell.x_left, cell.x_right) for ip in 0:np_cell, jp in 0:np_cell @@ -475,13 +470,13 @@ function _extension!(cell_mat::Array{ComplexF64,4}, cell_rhs::Matrix{ComplexF64} if cell.etype == CT_EXT # Asymptotic basis at right boundary of ext cell - ua_bdy, dua_bdy = _physical_ua_dua(cache, cell.x_right) + ua_bdy, dua_bdy = physical_ua_dua(cache, cell.x_right) ep = np_cell + 1 # index of the extra DOF (1-based → ep+1 in array) @inbounds for iq in 1:nq x = x0c + dxc * quad_nodes[iq] w = dxc * quad_weights[iq] - uax, duax = _physical_ua_dua(cache, x) + uax, duax = physical_ua_dua(cache, x) Imat, Umat, Vmat = _physical_uv(params, Q, x) pb, qb = _hermite(x, cell.x_left, cell.x_right) @@ -532,11 +527,11 @@ function _extension!(cell_mat::Array{ComplexF64,4}, cell_rhs::Matrix{ComplexF64} pb, qb = _hermite(x, cell.x_left, cell.x_right) if cell.etype == CT_EXT1 - uax, duax = _physical_ua_dua(cache, x) + uax, duax = physical_ua_dua(cache, x) ua_drv = uax[:, 2] dua_drv = duax[:, 2] else # CT_EXT2 - ua_bdy, dua_bdy = _physical_ua_dua(cache, cell.x_right) + ua_bdy, dua_bdy = physical_ua_dua(cache, cell.x_right) ua_drv = ua_bdy[:, 2] * pb[3] + dua_bdy[:, 2] * pb[4] dua_drv = ua_bdy[:, 2] * qb[3] + dua_bdy[:, 2] * qb[4] end @@ -570,7 +565,7 @@ function _resonant_integral(cell::GalerkinCell, params::GGJParameters, # u_res[1,2] = ∫ ua_1^T L ua_2 dx (RHS/driving) # Weak form after IBP: (test') I (trial') + (test) V (trial') + (test) U (trial) function integrand_11(x) - ua, dua = _physical_ua_dua(cache, x) + ua, dua = physical_ua_dua(cache, x) Imat, Umat, Vmat = _physical_uv(params, Q, x) ua1 = ua[:, 1] dua1 = dua[:, 1] @@ -578,7 +573,7 @@ function _resonant_integral(cell::GalerkinCell, params::GGJParameters, end function integrand_12(x) - ua, dua = _physical_ua_dua(cache, x) + ua, dua = physical_ua_dua(cache, x) Imat, Umat, Vmat = _physical_uv(params, Q, x) dua1 = dua[:, 1] ua1 = ua[:, 1] @@ -622,21 +617,7 @@ function _assemble_and_solve!(ws::GalerkinWorkspace, np_eff = cell.np fill!(cell_mat, 0) _gauss_quad!(cell_mat, cell, quad_nodes, quad_weights, params, Q) - - # Assemble into global banded matrix (both parities use same base matrix) - for ip in 0:np_eff, ipert in 1:mpert - i = cell.map[ipert, ip+1] - if i > ws.ndim - continue - end - for jp in 0:np_eff, jpert in 1:mpert - j = cell.map[jpert, jp+1] - if j > ws.ndim - continue - end - ws.mat[offset+i-j, j, 1] += cell_mat[ipert, jpert, ip+1, jp+1] - end - end + _scatter_cell!(ws, cell, cell_mat, np_eff) end # Extension terms @@ -693,7 +674,7 @@ function _assemble_and_solve!(ws::GalerkinWorkspace, # here (not dropped) because the resonant cell carries the matching data. res_cell = ws.cells[ws.nx] x_lsode = res_cell.x_lsode - ua_xmax, dua_xmax = _physical_ua_dua(cache, x_lsode) + ua_xmax, dua_xmax = physical_ua_dua(cache, x_lsode) Imat_xmax, _, _ = _physical_uv(params, Q, x_lsode) emap1 = res_cell.emap[1] if emap1 <= ws.ndim @@ -705,6 +686,34 @@ function _assemble_and_solve!(ws::GalerkinWorkspace, ws.rhs[emap1, 1] += surf_12 end + _parity_bcs_and_solve!(ws, params, Q, ws.ndim) +end + +# Add one cell's Hermite block to the base (isol = 1) banded matrix; both parities share it. +function _scatter_cell!(ws::GalerkinWorkspace, cell::GalerkinCell, cell_mat::Array{ComplexF64,4}, np_eff::Int) + mpert = 3 + offset = ws.kl + ws.kl + 1 + for ip in 0:np_eff, ipert in 1:mpert + i = cell.map[ipert, ip+1] + if i > ws.ndim + continue + end + for jp in 0:np_eff, jpert in 1:mpert + j = cell.map[jpert, jp+1] + if j > ws.ndim + continue + end + ws.mat[offset+i-j, j, 1] += cell_mat[ipert, jpert, ip+1, jp+1] + end + end +end + +# Copy the base system to both parities, impose the x = 0 parity conditions, and solve the +# leading n×n banded system of each parity by LAPACK banded LU. +function _parity_bcs_and_solve!(ws::GalerkinWorkspace, params::GGJParameters, Q::ComplexF64, n::Int) + mpert = 3 + offset = ws.kl + ws.kl + 1 + # Copy base matrix/rhs for both parities ws.mat[:, :, 2] .= ws.mat[:, :, 1] ws.rhs[:, 2] .= ws.rhs[:, 1] @@ -738,7 +747,7 @@ function _assemble_and_solve!(ws::GalerkinWorkspace, continue end - for jj in max(1, i-ws.kl):min(ws.ndim, i+ws.kl) + for jj in max(1, i - ws.kl):min(ws.ndim, i + ws.kl) ws.mat[offset+i-jj, jj, isol] = 0 end end @@ -778,16 +787,93 @@ function _assemble_and_solve!(ws::GalerkinWorkspace, end # Solve for each parity using LAPACK banded LU (gbtrf! + gbtrs!) - n = ws.ndim kl = ws.kl ku = kl + ab = @view ws.ab_buf[:, 1:n] + rb = @view ws.rhs_buf[1:n] + for isol in 1:2 + copyto!(ab, @view(ws.mat[:, 1:n, isol])) + copyto!(rb, @view(ws.rhs[1:n, isol])) + _, ipiv = LinearAlgebra.LAPACK.gbtrf!(kl, ku, n, ab) + LinearAlgebra.LAPACK.gbtrs!('N', kl, ku, n, ab, ipiv, rb) + ws.sol[1:n, isol] .= rb + end +end + +""" + _assemble_and_solve_point!(ws, params, Q, θ, Us, Ub, E; nq=6) -> (Δraw, cexp) + +Hermite Galerkin solve on the all-`CT_NONE` grid of `ws` along the ray x = e^{iθ}s, with the +far-field condition imposed at the last node instead of resonant/extension cells: its state is +v = Us + Δ·Ub + c₁E₁ + c₂E₂, with Us, Ub, E given as (Ψ, Ξ, Υ, Ψ', Ξ', Υ') in x-derivatives. The last node's six +DOFs are replaced by (Δ, c₁, c₂) and tested in the same three directions, as the extension cell +does for the stock backend. Returns the raw Δ and decaying-pair coefficients per parity +(isol = 1 odd, 2 even); `ws.sol` holds the full nodal solution afterwards. +""" +function _assemble_and_solve_point!(ws::GalerkinWorkspace, params::GGJParameters, Q::ComplexF64, + θ::Float64, Us::Vector{ComplexF64}, Ub::Vector{ComplexF64}, E::Matrix{ComplexF64}; nq::Int=6) + quad_nodes, quad_weights = gausslobatto(nq + 1) + offset = ws.kl + ws.kl + 1 + N = ws.nx + fill!(ws.mat, 0) + fill!(ws.rhs, 0) + cell_mat = ws.cell_mat_buf + for ix in 1:(N-1) + _gauss_quad!(cell_mat, ws.cells[ix], quad_nodes, quad_weights, params, Q; θ=θ) + _scatter_cell!(ws, ws.cells[ix], cell_mat, ws.cells[ix].np) + end + + # Replaces GWP2016 ext/res cells: the far-field state is imposed strongly at the last node. + # Last cell as a dense 12×12 block, local DOF index 3·ip + ipert (ip = 0..3 Hermite slots). + cell = ws.cells[N] + _gauss_quad!(cell_mat, cell, quad_nodes, quad_weights, params, Q; θ=θ) + Kc = zeros(ComplexF64, 12, 12) + for ip in 0:3, jp in 0:3, ipert in 1:3, jpert in 1:3 + Kc[3ip+ipert, 3jp+jpert] = cell_mat[ipert, jpert, ip+1, jp+1] + end + # IBP boundary term at the far end, mirroring the x = 0 term of `_parity_bcs_and_solve!` (I is x-independent). + Imat, _, _ = _physical_uv(params, Q, 0.0) + for ipert in 1:3, jpert in 1:3 + Kc[6+ipert, 9+jpert] -= Imat[ipert, jpert] + end + + # Far-field trace in DOF units (values, s-derivatives = e^{iθ}·x-derivatives); Ub normalized. + dof(v) = ComplexF64[v[1], v[2], v[3], cis(θ)*v[4], cis(θ)*v[5], cis(θ)*v[6]] + βb = norm(Ub) + Bd = hcat(dof(Ub) ./ βb, dof(E[:, 1]), dof(E[:, 2])) + usd = dof(Us) + # Tl maps the 9 reduced unknowns (left node's 6 DOFs, Δ̃, c₁, c₂) to the cell's 12 Hermite DOFs; test space = Tlᵀ. + Tl = zeros(ComplexF64, 12, 9) + for k in 1:6 + Tl[k, k] = 1 + end + Tl[7:12, 7:9] .= Bd + K9 = transpose(Tl) * Kc * Tl + r9 = -(transpose(Tl) * (Kc[:, 7:12] * usd)) + # (Δ̃, c₁, c₂) occupy the last node's value slots; its derivative slots drop out of the reduced system. + yslots = cell.map[:, 3] + glob = vcat(cell.map[:, 1], cell.map[:, 2], yslots) + for a in 1:9 + i = glob[a] + ws.rhs[i, 1] += r9[a] + for b in 1:9 + j = glob[b] + ws.mat[offset+i-j, j, 1] += K9[a, b] + end + end + + _parity_bcs_and_solve!(ws, params, Q, yslots[end]) + + Δraw = MVector{2,ComplexF64}(0, 0) + cexp = zeros(MMatrix{2,2,ComplexF64}) for isol in 1:2 - copyto!(ws.ab_buf, @view(ws.mat[:, :, isol])) - copyto!(ws.rhs_buf, @view(ws.rhs[:, isol])) - _, ipiv = LinearAlgebra.LAPACK.gbtrf!(kl, ku, n, ws.ab_buf) - LinearAlgebra.LAPACK.gbtrs!('N', kl, ku, n, ws.ab_buf, ipiv, ws.rhs_buf) - ws.sol[:, isol] .= ws.rhs_buf + y = ws.sol[yslots, isol] + Δraw[isol] = y[1] / βb + cexp[1, isol] = y[2] + cexp[2, isol] = y[3] + ws.sol[vcat(cell.map[:, 3], cell.map[:, 4]), isol] .= usd .+ Bd * y # reconstruct the last node for profiles end + return SVector(Δraw), SMatrix(cexp) end # ----------------------------------------------------------------------- diff --git a/src/InnerLayer/GGJ/InnerAsymptotics.jl b/src/InnerLayer/GGJ/InnerAsymptotics.jl index 1c752bf8d..127ccaa14 100644 --- a/src/InnerLayer/GGJ/InnerAsymptotics.jl +++ b/src/InnerLayer/GGJ/InnerAsymptotics.jl @@ -289,7 +289,7 @@ function _coefs(B::Vector{SMatrix{6,6,ComplexF64,36}}, # C_k = [[0, 0], [K2[2,1], K2[1,1] + K2[2,2]]] Cm[k+1] = @SMatrix ComplexF64[ 0 0 - K2acc[2, 1] K2acc[1, 1] + K2acc[2, 2] + K2acc[2, 1] K2acc[1, 1]+K2acc[2, 2] ] end @@ -382,10 +382,10 @@ build_asymptotics(params::GGJParameters, Q::Number; kmax::Int=8) = # and dy[i] = d/dx of the above. # # `c` is an n_components × (n+1) matrix; the second axis is k = 0..n, -# 1-indexed in Julia. +# 1-indexed in Julia. `x` may be real or complex (principal branch of x^rvec). # ----------------------------------------------------------------------- -function _horner(x::Real, c::AbstractMatrix{ComplexF64}; +function _horner(x::Number, c::AbstractMatrix{ComplexF64}; rvec::Union{Nothing,AbstractVector{<:Real}}=nothing, derivative::Bool=false) nrows, ncols = size(c) @@ -488,11 +488,12 @@ end # ----------------------------------------------------------------------- """ - evaluate_asymptotics(cache::InnerAsymptoticsCache, x::Real; derivative=true, apply_T=true) -> (U, dU) + evaluate_asymptotics(cache::InnerAsymptoticsCache, x::Number; derivative=true, apply_T=true) -> (U, dU) -Evaluate the inps asymptotic basis at `x > 0`. Returns the 6×2 complex -matrix `U` whose two columns are the algebraically-decaying ("small") -asymptotic solutions of the GGJ system, and (if `derivative=true`) the +Evaluate the inps asymptotic basis at `x`, real (`x > 0`) or complex on a +rotated contour (principal branch of `x^r`; the series is in 1/x², so valid for |arg x| < π/2). +Returns the 6×2 complex matrix `U` whose two columns are the power-like (Mercier) solutions of +the GGJ system (column 1 large, column 2 small), and (if `derivative=true`) the 6×2 matrix `dU` of their derivatives `dU/dx`. If `apply_T=false`, the result is left in the J-rotated coordinate basis @@ -500,7 +501,7 @@ If `apply_T=false`, the result is left in the J-rotated coordinate basis returns the solutions in the original 6-component first-order-system basis used by `_physical_uv` and the shooting / Galerkin solvers. """ -function evaluate_asymptotics(cache::InnerAsymptoticsCache, x::Real; +function evaluate_asymptotics(cache::InnerAsymptoticsCache, x::Number; derivative::Bool=true, apply_T::Bool=true) xfac = 1.0 / (x * x) R = cache.R @@ -569,6 +570,29 @@ function evaluate_asymptotics(cache::InnerAsymptoticsCache, x::Real; end end +""" + physical_ua_dua(cache, x::Number) -> (ua, dua) + +Convert the inps 6×2 basis at real or complex `x` to physical `(Ψ, Ξ, Υ)` +values and x-derivatives, each 3×2 (column 1 = large power solution, 2 = small). +The inps columns are in the GW2020 Eq. (2) state `u = (xΨ, Ξ, Υ, (xΨ)'/x, Ξ'/x, Υ'/x)`, +hence the /x and ·x factors; same map as the deltac `inpso_get_ua/dua` convention. +""" +function physical_ua_dua(cache::InnerAsymptoticsCache, x::Number) + U, dU = evaluate_asymptotics(cache, x; derivative=true, apply_T=true) + ua = zeros(ComplexF64, 3, 2) + dua = zeros(ComplexF64, 3, 2) + @inbounds for j in 1:2 + ua[1, j] = U[1, j] / x + ua[2, j] = U[2, j] + ua[3, j] = U[3, j] + dua[1, j] = U[4, j] - U[1, j] / (x * x) + dua[2, j] = U[5, j] * x + dua[3, j] = U[6, j] * x + end + return ua, dua +end + # ----------------------------------------------------------------------- # Residual `delta` and adaptive xmax — the convergence measure Δ± of GW2020 # Eq. (54), ‖u' − xJu‖/max(‖u'‖,‖xJu‖) in the J-rotated basis, used to choose @@ -576,15 +600,15 @@ end # ----------------------------------------------------------------------- """ - asymptotic_residual(cache::InnerAsymptoticsCache, x::Real) -> SVector{2,Float64} + asymptotic_residual(cache::InnerAsymptoticsCache, x::Number) -> SVector{2,Float64} -Compute the convergence measure `Δ±` of the asymptotic basis at `x` for each +Compute the convergence measure `Δ±` of the asymptotic basis at real or complex `x` for each of the two algebraic columns (GW2020 Eq. 54). Returns `‖dU − x·matrix·U‖∞ / max(‖dU‖∞, ‖x·matrix·U‖∞)` per column, where `matrix = J₀ + xfac·J₁ + xfac²·J₂` is the J-rotated coefficient matrix (the residual of `v' = xJv`, GW2020 Eq. 6). """ -function asymptotic_residual(cache::InnerAsymptoticsCache, x::Real) +function asymptotic_residual(cache::InnerAsymptoticsCache, x::Number) U, dU = evaluate_asymptotics(cache, x; derivative=true, apply_T=false) xfac = 1.0 / (x * x) @@ -651,3 +675,38 @@ end pick_xmax(params::GGJParameters, Q::Number; kwargs...) = pick_xmax(params, ComplexF64(Q); kwargs...) + +""" + pick_smax(params, Q; θ=angle(Q)/4, eps=1e-9, kmax=12, cache=nothing, + slogmin=-1.0, slogmax=6.5, dslog=0.01) -> (S, cache, achieved) + +Rotated-contour analog of [`pick_xmax`](@ref): the smallest `s` at which the series +residual along `x = e^{iθ}s` drops below `eps`. If never reached, returns the +residual-minimizing `s` with `achieved = false`. +""" +function pick_smax(params::GGJParameters, Q::ComplexF64; + θ::Float64=angle(Q) / 4, eps::Float64=1e-9, kmax::Int=12, + cache::Union{Nothing,InnerAsymptoticsCache}=nothing, + slogmin::Float64=-1.0, slogmax::Float64=6.5, dslog::Float64=0.01) + c = cache === nothing ? build_asymptotics(params, Q; kmax=kmax) : cache + ph = cis(θ) + best_s = 10.0^slogmin + best_r = Inf + slog = slogmin + while slog <= slogmax + s = 10.0^slog + r = maximum(asymptotic_residual(c, ph * s)) + if r < eps + return s, c, true + end + if r < best_r + best_r = r + best_s = s + end + slog += dslog + end + return best_s, c, false +end + +pick_smax(params::GGJParameters, Q::Number; kwargs...) = + pick_smax(params, ComplexF64(Q); kwargs...) diff --git a/src/InnerLayer/GGJ/Ray.jl b/src/InnerLayer/GGJ/Ray.jl index 8440432f6..9261a1027 100644 --- a/src/InnerLayer/GGJ/Ray.jl +++ b/src/InnerLayer/GGJ/Ray.jl @@ -1,36 +1,22 @@ # Ray.jl # -# Rotated-contour spectral-element collocation backend (`GGJModel{:ray}`) -# for the GGJ inner-layer matching data — robust at large |Q| on and near -# the imaginary axis, where both `:shooting` (exponential dichotomy) and -# `:galerkin` (real-axis oscillation + on-axis pseudo-resonance) degrade. +# Rotated-contour backend (`GGJModel{:ray}`) for the GGJ inner-layer matching data, +# robust at large |Q| where the stock `:galerkin` matching degrades. Method write-up: +# docs/src/inner_layer.md, "Numerical method". # -# Validated against the Fortran rmatch pins, the `:galerkin` backend at -# moderate Q, and physical benchmarks to Q = 500i. Summarized method write-up: -# docs/src/inner_layer.md, "Numerical method". In one paragraph: -# -# The equations are continued analytically onto the ray x = e^{iθ}s with -# θ = arg(Q)/4 (parabolic-cylinder exponent exactly real; pseudo-resonance -# cleared). On [0, s_m] a global Chebyshev spectral-element collocation BVP -# in the plain variables v = (Ψ, Ξ, Υ, Ψ', Ξ', Υ') is solved with parity -# conditions at the (ordinary-point) origin and Δ, c₁, c₂ as bordered -# unknowns of one sparse LU per parity (rank-3 Woodbury for the second). -# The far-field condition uses the SAME inps Wasow basis as the other -# backends (RayAsymptotics.jl evaluates it at complex x; the rdcon -# normalization of Δ is retained), applied at the series radius S and -# transported S → s_m by an L-stable 2-stage Radau IIA march in the -# quotient modulo the decaying exponential pair. The damped-zone march -# arithmetic runs in Complex{Double64}: at large S the near-parallel -# power-pair geometry amplifies the structured backward error of the -# ill-conditioned implicit solves (Σ eps·z ≈ eps·ρS²/2) into Δ-mixing -# ~1e-4 at |Q| = 500 in Float64 (docs/src/inner_layer.md, "Far-field -# boundary and the inward march"). +# The equations are continued analytically onto the ray x = e^{iθ}s, θ = arg(Q)/4 +# (parabolic-cylinder exponent exactly real; pseudo-resonance off the contour). The +# far-field condition uses the same inps Wasow basis as the other backends, applied at +# the series radius S and transported S → s_m by an L-stable 2-stage Radau IIA march in +# the quotient modulo the decaying exponential pair (damped zone in Complex{Double64}). +# On [0, s_m] the stock Hermite-cubic Galerkin assembly (Galerkin.jl) solves the BVP with +# parity conditions at the origin and v(s_m) = Us + Δ·Ub + c₁E₁ + c₂E₂ at the far end. # # File layout: -# 1. system — plain-variable first-order ODE matrix, parity sets -# 2. mesh — Chebyshev cells, barycentric interpolation, WKB grading +# 1. system — plain-variable first-order ODE matrix (used by the march), parity sets +# 2. mesh — WKB-graded Hermite grid on [0, s_m] # 3. boundary — decaying pair, Radau IIA quotient march -# 4. solve — assembly, bordered solve, refinement, driver, diagnostics +# 4. solve — driver, profiles, convergence battery # system.jl # @@ -103,140 +89,28 @@ each parity solution, mirroring deltac_set_boundary: """ parity_rows(isol::Int) = isol == 1 ? SVector(4, 2, 3) : SVector(1, 5, 6) # mesh.jl -# -# Graded spectral-element mesh on the ray parameter s ∈ [0, S], plus the -# Chebyshev–Lobatto reference-cell machinery (nodes, differentiation matrix, -# barycentric interpolation). -# -# The initial grading tracks the local stiffness scales of the rotated -# system: -# - the fast Ohm's-law pair e^{±√Q x}: active near the origin, decaying -# at rate Re(√Q e^{iθ}) — resolved on a fine zone [0, s₁]; -# - the parabolic-cylinder pair e^{±ρ s²/2}, ρ = Re(e^{2iθ}/√Q): decaying -# content is above relative machine floor only for s ≲ s_d = √(2D/ρ) — -# resolved on a rate-adapted zone [s₁, s_d]; -# - beyond s_d the physical solution is a smooth power law: geometric -# (log-spaced) cells suffice out to S. -# Residual-driven bisection refinement (solve.jl) then repairs whatever the -# initial guess missed. - -""" - cheblobatto(p) -> (t, D) - -Chebyshev–Lobatto nodes on [-1, 1] in ASCENDING order and the spectral -differentiation matrix `D` for those nodes (Trefethen's `cheb`, reflected). -""" -function cheblobatto(p::Int) - p >= 1 || throw(ArgumentError("polynomial order p must be ≥ 1")) - # Standard descending Trefethen nodes x_j = cos(jπ/p), j = 0..p. - x = [cos(pi * j / p) for j in 0:p] - c = [j == 0 || j == p ? 2.0 : 1.0 for j in 0:p] .* [(-1.0)^j for j in 0:p] - D = zeros(p + 1, p + 1) - for i in 1:(p+1), j in 1:(p+1) - if i != j - D[i, j] = (c[i] / c[j]) / (x[i] - x[j]) - end - end - for i in 1:(p+1) - D[i, i] = -sum(D[i, j] for j in 1:(p+1) if j != i) - end - # Reflect to ascending order: y = -x is ascending with the SAME index - # order (x is descending), and for g(y) := f(-y) sampled on y the chain - # rule gives D_y = -D. No index permutation. - t = -x - Dt = -D - return t, Dt -end - -""" - barycentric_weights(t) -> w - -Barycentric interpolation weights for nodes `t` (any distribution). -""" -function barycentric_weights(t::AbstractVector{Float64}) - n = length(t) - w = ones(Float64, n) - for j in 1:n - for k in 1:n - k == j && continue - w[j] /= (t[j] - t[k]) - end - end - return w -end - -""" - barycentric_eval(t, w, vals, τ) -> value - -Evaluate the interpolant of `vals` (matrix: nodes × components) at `τ`. -Returns a vector over components. -""" -function barycentric_eval(t::AbstractVector{Float64}, w::AbstractVector{Float64}, - vals::AbstractMatrix{ComplexF64}, τ::Float64) - n = length(t) - for j in 1:n - if τ == t[j] - return vals[j, :] - end - end - num = zeros(ComplexF64, size(vals, 2)) - den = 0.0 - for j in 1:n - fac = w[j] / (τ - t[j]) - den += fac - @views num .+= fac .* vals[j, :] - end - return num ./ den -end """ - initial_breaks(params, Q, θ, S, p; cfl=0.4, drop=40.0, ratio=1.3, - hmax_frac=0.08) -> Vector{Float64} + ray_breaks(params, Q, θ, S; cfl=0.2, min_cells=1024) -> Vector{Float64} -Build the initial cell-boundary vector `0 = s₀ < s₁ < … = S` using the -three-zone grading described in the header. `cfl` ≈ resolved-exponential -rate per node; `drop` = e-folds after which decaying exponential content is -considered machine-dead; `ratio` = geometric growth in the outer zone. +Cell boundaries `0 = s₀ < s₁ < … = S` for the Hermite BVP: each cell resolves the full +local WKB rate μ + ρs (fast Ohm and Υ-family pair μ = |√Q| + √(|Q|·|G+KF|), parabolic pair +ρ = Re(e^{2iθ}/√Q)) whether or not the mode is present, since unresolved dormant modes +alias into spurious discrete ones. `min_cells` floors the resolution where the local rates +are small (|Q| ≪ 1). """ -function initial_breaks(params::GGJParameters, Q::ComplexF64, θ::Float64, - S::Float64, p::Int; cfl::Float64=0.4, drop::Float64=40.0, - ratio::Float64=1.3, hmax_frac::Float64=0.08) +function ray_breaks(params::GGJParameters, Q::ComplexF64, θ::Float64, S::Float64; + cfl::Float64=0.2, min_cells::Int=1024) sq = sqrt(Q) - ρ = real(cis(2θ) / sq) # parabolic pair: exponent ρ s²/2 + ρ = real(cis(2θ) / sq) ρ > 0 || throw(ArgumentError("contour angle θ=$θ gives non-decaying parabolic pair (ρ=$ρ ≤ 0); use θ ≈ arg(Q)/4")) - # Fast local WKB scales: the Ohm pair |√Q| and the Υ-family - # √|Q(G+KF)| (dominant on extreme-coefficient surfaces, K ~ 10⁶ — - # dormant almost everywhere but must be resolved; see solve.jl header). μ = abs(sq) + sqrt(abs(Q) * abs(params.G + params.K * params.F)) - μdec = max(real(sq * cis(θ)), 0.1 * μ) # its decay rate along the ray - - s1 = min(drop / μdec, 0.7 * S) # fast pair dead beyond s1 - sd = min(sqrt(2 * drop / ρ), 0.8 * S) # parabolic pair dead beyond sd - sd = max(sd, min(1.05 * s1, S)) - hmax = hmax_frac * S - - # Single grading rule: every cell resolves the full local WKB rate - # μ + ρs (fast pair + parabolic pair), whether the corresponding mode - # amplitudes are alive or dormant — unresolved dormant modes alias into - # spurious bounded discrete modes and poison the global solve. The - # outer power-law region is not discretized at all (handled by the - # boundary march), so this never gets expensive: the BVP domain ends at - # s_m ~ max(s_d, s₁) where μ dominates the rate budget. - _ = (s1, sd, ratio) # zone markers retained in signature for tuning + hmax = S / min_cells breaks = [0.0] while breaks[end] < S - s = breaks[end] - h = cfl * p / (μ + ρ * s) - h = min(h, hmax, S / 8) - snew = s + h - if snew >= S - 0.25 * h - snew = S - end - push!(breaks, min(snew, S)) - end - # Guard against a degenerate final sliver. - if length(breaks) >= 3 && (breaks[end] - breaks[end-1]) < 0.2 * (breaks[end-1] - breaks[end-2]) - deleteat!(breaks, length(breaks) - 1) + h = min(cfl / (μ + ρ * breaks[end]), hmax) + snew = breaks[end] + h + push!(breaks, snew >= S - 0.25 * h ? S : snew) end return breaks end @@ -251,7 +125,7 @@ end # # The inps series is only trusted at radius S (residual ≤ smax_tol), which # for extreme-coefficient surfaces (K ~ 10⁶) can be S ~ 10⁴–10⁵, while the -# collocation BVP ends at s_m ~ 30–150. The gap is bridged by MARCHING the +# BVP ends at s_m ~ 30–150. The gap is bridged by MARCHING the # power-pair data W = [u_small, u_big] backward S → s_m. # # Marching design (the hard-won part): @@ -366,7 +240,7 @@ function march_boundary(params::GGJParameters, Q::ComplexF64, θ::Float64, function radau_step(s, W, h) M1 = 𝔐(s + h / 3) M2 = 𝔐(s + h) - Ablk = [I6-(5h/12)*M1 (h/12)*M1; -(3h/4)*M2 I6-(h/4)*M2] + Ablk = [I6-(5h/12)*M1 (h/12)*M1; -(3h / 4)*M2 I6-(h/4)*M2] rhs = [M1 * W; M2 * W] K = Ablk \ rhs return W + h * ((3 / 4) * @view(K[1:6, :]) + (1 / 4) * @view(K[7:12, :])) @@ -391,7 +265,7 @@ function march_boundary(params::GGJParameters, Q::ComplexF64, θ::Float64, hd = Double64(h) M1 = 𝔐d(s + h / 3) M2 = 𝔐d(s + h) - Ablk = [I6d-(5hd/12)*M1 (hd/12)*M1; -(3hd/4)*M2 I6d-(hd/4)*M2] + Ablk = [I6d-(5hd/12)*M1 (hd/12)*M1; -(3hd / 4)*M2 I6d-(hd/4)*M2] rhs = [M1 * Wd; M2 * Wd] K = Ablk \ rhs return Wd + hd * ((CTd(3) / 4) * K[1:6, :] + (CTd(1) / 4) * K[7:12, :]) @@ -529,231 +403,42 @@ end # solve.jl # -# Global spectral-element collocation solve of the GGJ inner-layer BVP on -# the rotated ray, with the matching data Δ as a bordered unknown. -# -# For each parity (deltac isol = 1 "odd", 2 "even"): -# -# unknowns : v at all global nodes (6 components each), plus (Δ, c₁, c₂) -# equations: dv/ds = e^{iθ} M(e^{iθ}s) v collocated at the p non-left -# Lobatto nodes of every cell (right-biased collocation — -# Radau-IIA-like, stable for the stiff modes); -# 3 parity conditions at s = 0; -# 6 matching conditions at s = S: -# v(S) − Δ·Ub − c₁E₁ − c₂E₂ = Us . -# -# One sparse LU per parity per mesh; residual-driven bisection refinement. -# The exponential dichotomy never enters: no quantity is ever propagated -# across the layer, and the boundary condition splits the dichotomy exactly. +# Driver: series radius S, BVP edge s_m, march S → s_m, then the Hermite Galerkin BVP on +# [0, s_m] with the far-field state v(s_m) = Us + Δ·Ub + c₁E₁ + c₂E₂ (Galerkin.jl, +# `_assemble_and_solve_point!`). """ RaySolveResult -Output of [`solve_ray`](@ref). `Δ` is the rescaled matching data in the -deltac output ordering (index 1 ↔ even-BC solution, 2 ↔ odd-BC solution, -i.e. the same swap deltac_solve applies); `Δraw` is (isol=1, isol=2) in raw -inps normalization before `rescale_delta`. +Output of [`solve_ray`](@ref). + +## Fields + + - `Δ`: rescaled matching data in the deltac output ordering (index 1 ↔ even-BC solution, + 2 ↔ odd-BC solution, the same swap deltac_solve applies). + - `Δraw`: (isol = 1, isol = 2) in raw inps normalization, before `rescale_delta`. + - `cexp`: decaying-pair coefficients (c₁, c₂) at s_m, one column per parity. + - `Q`, `θ`: scaled eigenvalue and contour angle. + - `S`: series radius where the far-field data were taken. + - `series_ok`: whether `pick_smax` reached its residual tolerance. + - `bc_cond`: condition number of the column-normalized boundary basis [Us, Ub, E]. + - `breaks`: Hermite cell boundaries on [0, s_m]. + - `cfl`, `min_cells`: mesh resolution parameters used by [`ray_breaks`](@ref). + - `ws`: the full Galerkin workspace of the BVP (system buffers included); the nodal solution is `ws.sol`, both parities. """ struct RaySolveResult Δ::SVector{2,ComplexF64} Δraw::SVector{2,ComplexF64} - cexp::SMatrix{2,2,ComplexF64,4} # decaying-pair coefficients (col = isol) + cexp::SMatrix{2,2,ComplexF64,4} Q::ComplexF64 θ::Float64 S::Float64 - series_ok::Bool # pick_smax reached its tolerance - bc_cond::Float64 # boundary-basis condition number + series_ok::Bool + bc_cond::Float64 breaks::Vector{Float64} - p::Int - sols::Matrix{ComplexF64} # ndof × 2 nodal solution (isol = 1, 2) - resid::Float64 # final max relative collocation residual - δΔ_refine::Float64 # |Δ change| in last refinement round (rel) - nrounds::Int -end - -# ----------------------------------------------------------------------- -# Assembly. -# ----------------------------------------------------------------------- - -function _assemble_base(params::GGJParameters, Q::ComplexF64, θ::Float64, - breaks::Vector{Float64}, p::Int, - t::Vector{Float64}, D::Matrix{Float64}, - Us::Vector{ComplexF64}, Ub::Vector{ComplexF64}, E::Matrix{ComplexF64}) - N = length(breaks) - 1 - Ng = N * p + 1 - ndof = 6 * Ng + 3 - ph = cis(θ) - βb = norm(Ub) - - nnz_est = N * p * 6 * (p + 7) + 24 + 3 - Ic = Vector{Int}() - Jc = Vector{Int}() - Vc = Vector{ComplexF64}() - sizehint!(Ic, nnz_est) - sizehint!(Jc, nnz_est) - sizehint!(Vc, nnz_est) - - @inbounds for c in 1:N - a, b = breaks[c], breaks[c+1] - Dscale = 2 / (b - a) - for j in 1:p - s_j = a + (b - a) * (t[j+1] + 1) / 2 - M = ph * ode_matrix(params, Q, ph * s_j) - row0 = 6 * ((c - 1) * p + (j - 1)) - gj = (c - 1) * p + j + 1 - for i in 1:6 - row = row0 + i - for k in 0:p - gk = (c - 1) * p + k + 1 - push!(Ic, row) - push!(Jc, 6 * (gk - 1) + i) - push!(Vc, Dscale * D[j+1, k+1]) - end - for i2 in 1:6 - Mv = M[i, i2] - if Mv != 0 - push!(Ic, row) - push!(Jc, 6 * (gj - 1) + i2) - push!(Vc, -Mv) - end - end - end - end - end - - # Matching rows at s = S. - rowm0 = 6 * N * p - @inbounds for i in 1:6 - row = rowm0 + i - push!(Ic, row) - push!(Jc, 6 * (Ng - 1) + i) - push!(Vc, one(ComplexF64)) - push!(Ic, row) - push!(Jc, 6 * Ng + 1) - push!(Vc, -Ub[i] / βb) - push!(Ic, row) - push!(Jc, 6 * Ng + 2) - push!(Vc, -E[i, 1]) - push!(Ic, row) - push!(Jc, 6 * Ng + 3) - push!(Vc, -E[i, 2]) - end - - rhs = zeros(ComplexF64, ndof) - rhs[rowm0 .+ (1:6)] .= Us - - return Ic, Jc, Vc, rhs, βb, ndof, Ng -end - -""" - _solve_parities(Ic, Jc, Vc, rhs, ndof, N, p) -> (sol_odd, sol_even) - -Solve both parity systems from one factorization: the two matrices differ only -in the 3 parity rows at s = 0 (a rank-3 update), so one sparse LU of the -row-equilibrated odd system plus a Woodbury correction replaces the second -factorization, which dominates the linear-algebra cost. -""" -function _solve_parities(Ic::Vector{Int}, Jc::Vector{Int}, Vc::Vector{ComplexF64}, - rhs::Vector{ComplexF64}, ndof::Int, N::Int, p::Int) - rowp0 = 6 * N * p + 6 - c1 = parity_rows(1) - c2 = parity_rows(2) - I2 = copy(Ic) - J2 = copy(Jc) - V2 = copy(Vc) - for k in 1:3 - push!(I2, rowp0 + k) - push!(J2, c1[k]) - push!(V2, one(ComplexF64)) - end - A = sparse(I2, J2, V2, ndof, ndof) - - # Row equilibration. - rmax = zeros(Float64, ndof) - rows = rowvals(A) - vals = nonzeros(A) - for col in 1:ndof - for idx in nzrange(A, col) - r = rows[idx] - a = abs(vals[idx]) - a > rmax[r] && (rmax[r] = a) - end - end - @inbounds for i in 1:ndof - rmax[i] = rmax[i] > 0 ? 1 / rmax[i] : 1.0 - end - Dr = Diagonal(rmax) - F = lu(Dr * A) - x1 = F \ (Dr * rhs) - - # Woodbury: (DrA + U Vᵀ)⁻¹ b = x1 − A⁻¹U (I₃ + Vᵀ A⁻¹U)⁻¹ Vᵀ x1, - # with U[:,k] = Dr[rₖ,rₖ]·e_{rₖ} and Vᵀ[k,:] = (e_{c2ₖ} − e_{c1ₖ})ᵀ. - U = zeros(ComplexF64, ndof, 3) - for k in 1:3 - U[rowp0+k, k] = rmax[rowp0+k] - end - AinvU = F \ U - Vx1 = ComplexF64[x1[c2[k]] - x1[c1[k]] for k in 1:3] - Smat = Matrix{ComplexF64}(I, 3, 3) - for k in 1:3, j in 1:3 - Smat[k, j] += AinvU[c2[k], j] - AinvU[c1[k], j] - end - x2 = x1 - AinvU * (Smat \ Vx1) - # UMFPACK numeric factorizations live in C malloc, invisible to the GC's - # heap accounting — under the refinement loop, lazily-finalized multi-GB - # factorizations pile up (observed: tens of GB on 24k-cell meshes). Free - # eagerly now that both solutions are extracted. - finalize(F) - return x1, x2 -end - -# ----------------------------------------------------------------------- -# Residual estimation for adaptive refinement. -# ----------------------------------------------------------------------- - -function _cell_errors(params::GGJParameters, Q::ComplexF64, θ::Float64, - breaks::Vector{Float64}, p::Int, - t::Vector{Float64}, D::Matrix{Float64}, w::Vector{Float64}, - sol::Vector{ComplexF64}) - N = length(breaks) - 1 - ph = cis(θ) - errs = zeros(Float64, N) - - # Reference-cell test points: left endpoint + inter-node midpoints. - τs = Float64[-1.0] - for j in 1:p - push!(τs, (t[j] + t[j+1]) / 2) - end - - vals = Matrix{ComplexF64}(undef, p + 1, 6) - for c in 1:N - a, b = breaks[c], breaks[c+1] - Dscale = 2 / (b - a) - for j in 0:p - g = (c - 1) * p + j + 1 - for i in 1:6 - vals[j+1, i] = sol[6*(g-1)+i] - end - end - dvals = (Dscale .* D) * vals - - emax = 0.0 - for τ in τs - vτ = barycentric_eval(t, w, vals, τ) - dvτ = barycentric_eval(t, w, dvals, τ) - s_τ = a + (b - a) * (τ + 1) / 2 - Mv = (ph * ode_matrix(params, Q, ph * s_τ)) * vτ - rnorm = 0.0 - scale = 1e-300 - for i in 1:6 - rnorm = max(rnorm, abs(dvτ[i] - Mv[i])) - scale = max(scale, abs(dvτ[i]), abs(Mv[i])) - end - emax = max(emax, rnorm / scale) - end - errs[c] = emax - end - return errs + cfl::Float64 + min_cells::Int + ws::GalerkinWorkspace end # ----------------------------------------------------------------------- @@ -761,23 +446,21 @@ end # ----------------------------------------------------------------------- """ - solve_ray(params::GGJParameters, Q; θ=angle(Q)/4, kmax=12, p=12, S=nothing, - smax_tol=1e-9, refine_tol=1e-8, max_rounds=8, max_cells=6000, - verbose=false, kwargs...) -> RaySolveResult + solve_ray(params::GGJParameters, Q; θ=angle(Q)/4, kmax=12, S=nothing, smax_tol=1e-9, + cfl=0.2, min_cells=1024, nq=6, verbose=false, kwargs...) -> RaySolveResult Solve the GGJ inner-layer problem on the rotated ray x = e^{iθ}s. `Δ` follows the deltac output convention (swap + `rescale_delta`), directly comparable to the `:galerkin` backend. θ = 0 reproduces a real-axis solve; -`S` defaults to the inps series-residual radius (`pick_smax`); `p` is the -polynomial order per spectral element; remaining keywords are march/mesh -knobs (see `march_boundary`, `initial_breaks`, `decaying_pair`). +`S` defaults to the inps series-residual radius (`pick_smax`); `cfl`, `min_cells` set the +Hermite grid ([`ray_breaks`](@ref)) and `nq` its quadrature; remaining keywords are march +knobs (see `march_boundary`, `decaying_pair`). """ function solve_ray(params::GGJParameters, Q::ComplexF64; - θ::Float64=angle(Q) / 4, kmax::Int=12, p::Int=12, + θ::Float64=angle(Q) / 4, kmax::Int=12, S::Union{Nothing,Float64}=nothing, smax_tol::Float64=1e-9, - growth::Float64=30.0, refine_tol::Float64=1e-8, - march_rtol::Float64=1e-9, sm_fac::Float64=1.0, cfl::Float64=0.4, - max_rounds::Int=8, max_cells::Int=6000, seed::Int=20260707, + growth::Float64=30.0, march_rtol::Float64=1e-9, sm_fac::Float64=1.0, + cfl::Float64=0.2, min_cells::Int=1024, nq::Int=6, seed::Int=20260707, ztrk::Float64=0.3, purge_budget::Float64=2.5, dp_res::Float64=20.0, handoff::Union{Nothing,NTuple{2,Vector{ComplexF64}}}=nothing, boundary::Union{Nothing,Tuple{Vector{ComplexF64},Vector{ComplexF64},Matrix{ComplexF64}}}=nothing, @@ -792,14 +475,8 @@ function solve_ray(params::GGJParameters, Q::ComplexF64; Sv = S end - # Decide the BVP outer radius: the layer physics (exponential content - # above machine floor) ends at s_d; beyond that the solution is pure - # power law and is handled by the projected quotient march, not by - # collocation. For small |Q| (s_d ≳ S) no march is needed. - sq = sqrt(Q) - ρ = real(cis(2θ) / sq) - # BVP outer radius s_m: where every exponential solution family has - # decayed ≥ 45 e-folds from the origin, computed from the actual + # Beyond s_m the solution is pure power law, carried by the quotient march; for small |Q| (s_m ≳ S) no march is needed. + # s_m: where every exponential solution family has decayed ≥ 45 e-folds from the origin, computed from the actual # frozen-coefficient spectrum (the asymptotic ρs rate is wrong near the # origin for extreme-coefficient surfaces, where the Υ-family rate # √|Q(G+KF)| dominates and kills exponential content within s ~ O(1)). @@ -851,72 +528,16 @@ function solve_ray(params::GGJParameters, Q::ComplexF64; end bc_cond < 1e12 || @warn "boundary basis poorly conditioned (cond ≈ $bc_cond)" - t, D = cheblobatto(p) - w = barycentric_weights(t) - breaks = initial_breaks(params, Q, θ, Sbvp, p; cfl=cfl) - - Δraw = MVector{2,ComplexF64}(0, 0) - Δprev = MVector{2,ComplexF64}(NaN, NaN) - cexp = zeros(MMatrix{2,2,ComplexF64}) - local sols - resid = Inf - resid_prev = Inf - nstall = 0 - δΔ = Inf - round_used = 0 - - for round in 0:max_rounds - round_used = round - N = length(breaks) - 1 - Ic, Jc, Vc, rhs, βb, ndof, Ng = _assemble_base(params, Q, θ, breaks, p, t, D, Us, Ub, E) - sols = Matrix{ComplexF64}(undef, ndof, 2) - errs = zeros(Float64, N) - sol_odd, sol_even = _solve_parities(Ic, Jc, Vc, rhs, ndof, N, p) - for (isol, sol) in ((1, sol_odd), (2, sol_even)) - sols[:, isol] = sol - Δraw[isol] = sol[6*Ng+1] / βb - cexp[1, isol] = sol[6*Ng+2] - cexp[2, isol] = sol[6*Ng+3] - errs = max.(errs, _cell_errors(params, Q, θ, breaks, p, t, D, w, sol)) - end - resid = maximum(errs) - δΔ = maximum(abs.(Δraw .- Δprev) ./ (abs.(Δraw) .+ 1e-300)) - Δprev .= Δraw - verbose && @printf(" round %d: %d cells, resid %.2e, Δraw[1] = %.6e %+.6eim, δΔ = %.1e\n", - round, N, resid, real(Δraw[1]), imag(Δraw[1]), δΔ) - - (resid < refine_tol || round == max_rounds) && break - # Stagnation guard: on extreme-coefficient surfaces the residual - # bottoms out at the roundoff floor ε·‖M‖ (~10⁻⁸ ≫ refine_tol); - # refining past that plateau burns cells without informing Δ. Two - # consecutive rounds with < 2× improvement ⇒ converged-to-plateau. - nstall = resid > 0.5 * resid_prev ? nstall + 1 : 0 - resid_prev = resid - if nstall >= 2 - verbose && @printf(" refinement stagnated at resid %.2e (roundoff plateau) — stopping\n", resid) - break - end - marked = findall(>(refine_tol), errs) - isempty(marked) && break - if N + length(marked) > max_cells - @warn "solve_ray: cell budget ($max_cells) reached with resid=$resid" - break - end - newbreaks = Float64[breaks[1]] - for c in 1:N - if c in marked - push!(newbreaks, (breaks[c] + breaks[c+1]) / 2) - end - push!(newbreaks, breaks[c+1]) - end - breaks = newbreaks - end + breaks = ray_breaks(params, Q, θ, Sbvp; cfl=cfl, min_cells=min_cells) + ws = _galerkin_workspace(breaks, fill(CT_NONE, length(breaks) - 1)) + Δraw, cexp = _assemble_and_solve_point!(ws, params, Q, θ, Us, Ub, E; nq=nq) + verbose && @printf(" BVP: %d Hermite cells on [0, %.4g], Δraw[1] = %.6e %+.6eim\n", + length(breaks) - 1, Sbvp, real(Δraw[1]), imag(Δraw[1])) Δswapped = SVector{2,ComplexF64}(Δraw[2], Δraw[1]) # deltac_solve convention Δ = rescale_delta(Δswapped, params) - return RaySolveResult(Δ, SVector(Δraw), SMatrix(cexp), Q, θ, Sv, series_ok, - bc_cond, breaks, p, sols, resid, δΔ, round_used) + return RaySolveResult(Δ, Δraw, cexp, Q, θ, Sv, series_ok, bc_cond, breaks, cfl, min_cells, ws) end solve_ray(params::GGJParameters, Q::Number; kwargs...) = @@ -947,7 +568,7 @@ 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 +pseudo-resonance is a regular point of the BVP. The θ=0-vs-optimal-θ Δ agreement doubles as a runtime certificate (two maximally different contours through the same entire solutions): the relative mismatch is returned as `certΔ` and warns above `certify_rtol`. `npc` sets the profile @@ -965,79 +586,17 @@ function solve_inner_profile(::_BareGGJ{:ray}, params::GGJParameters, γ::Number return (; Δ=rr.Δ, x=prof.s, Ψ=prof.Ψ, Ξ=prof.Ξ, _profile_conversions(params)..., certΔ=certΔ) end -""" - evaluate_solution(res::RaySolveResult, s::Real; isol=1) -> SVector{6,ComplexF64} - -Evaluate the solved state v = (Ψ, Ξ, Υ, Ψ', Ξ', Υ') at ray parameter `s` -(diagnostic; barycentric interpolation on the containing cell). -""" -function evaluate_solution(res::RaySolveResult, s::Real; isol::Int=1) - breaks = res.breaks - p = res.p - (breaks[1] <= s <= breaks[end]) || throw(ArgumentError("s=$s outside [0, $(breaks[end])]")) - c = clamp(searchsortedlast(breaks, s), 1, length(breaks) - 1) - a, b = breaks[c], breaks[c+1] - t, _ = cheblobatto(p) - w = barycentric_weights(t) - vals = Matrix{ComplexF64}(undef, p + 1, 6) - for j in 0:p - g = (c - 1) * p + j + 1 - for i in 1:6 - vals[j+1, i] = res.sols[6*(g-1)+i, isol] - end - end - τ = 2 * (s - a) / (b - a) - 1 - return SVector{6,ComplexF64}(barycentric_eval(t, w, vals, τ)...) -end - """ solution_profile(res::RaySolveResult; npc=8) -> (; s, x, Ψ, Ξ, Υ) -Reconstruct (Ψ, Ξ, Υ) on the solution contour, `npc` points per cell; each -field is `npts × 2` with columns (odd, even) and `x = e^{iθ}s`. For rotated -solves the fields live on the ray — continuation back to real x is a +Reconstruct (Ψ, Ξ, Υ) on the solution contour from the Hermite nodal solution, `npc` +points per cell; each field is `npts × 2` with columns (odd, even) and `x = e^{iθ}s`. +For rotated solves the fields live on the ray — continuation back to real x is a separate (unstable) problem, by design. """ function solution_profile(res::RaySolveResult; npc::Int=8) - breaks = res.breaks - p = res.p - t, _ = cheblobatto(p) - w = barycentric_weights(t) - N = length(breaks) - 1 - npts = N * npc + 1 - s = Vector{Float64}(undef, npts) - Ψ = Matrix{ComplexF64}(undef, npts, 2) - Ξ = Matrix{ComplexF64}(undef, npts, 2) - Υ = Matrix{ComplexF64}(undef, npts, 2) - vals = Matrix{ComplexF64}(undef, p + 1, 6) - k = 0 - for c in 1:N - a, b = breaks[c], breaks[c+1] - for m in 0:(npc-1) - k += 1 - τ = -1 + 2 * m / npc - s[k] = a + (b - a) * (τ + 1) / 2 - for isol in 1:2 - for j in 0:p, i in 1:6 - vals[j+1, i] = res.sols[6*((c-1)*p+j)+i, isol] - end - v = barycentric_eval(t, w, vals, τ) - Ψ[k, isol] = v[1] - Ξ[k, isol] = v[2] - Υ[k, isol] = v[3] - end - end - end - # right endpoint - k += 1 - s[k] = breaks[end] - for isol in 1:2 - v = evaluate_solution(res, breaks[end]; isol=isol) - Ψ[k, isol] = v[1] - Ξ[k, isol] = v[2] - Υ[k, isol] = v[3] - end - return (; s=s, x=cis(res.θ) .* s, Ψ=Ψ, Ξ=Ξ, Υ=Υ) + prof = _solution_profile(res.ws; npc=npc) + return (; s=prof.x, x=cis(res.θ) .* prof.x, Ψ=prof.Ψ, Ξ=prof.Ξ, Υ=prof.Υ) end """ @@ -1067,28 +626,21 @@ function asymptotic_profile(params::GGJParameters, res::RaySolveResult, end """ - delta_convergence(params, Q; verbose=true, refine_tol=1e-9, - max_rounds=16, max_cells=12000, kwargs...) - -> (; Δ, spread, base, table) + delta_convergence(params, Q; verbose=true, kwargs...) -> (; Δ, spread, base, table) -Error bar for the matching data: solve at a strict baseline, then re-solve -with each numerical knob perturbed on an independent axis (contour angle θ, -element order p, series order/radius, refinement depth, march tolerance, -handoff radius, purification e-folds — see `variations` below) and report the -relative change of (Δ₁, Δ₂) per knob. θ is perturbed outward only: inward -moves toward the x² ≈ −Q²(G+KF) pseudo-resonance and measures the perturbed -solve, not the baseline. `spread` is the per-parity worst case over all knobs. +Error bar for the matching data: solve at the baseline, then re-solve with each +numerical knob perturbed on an independent axis (contour angle θ, mesh resolution, +series order/radius, march tolerance, handoff radius, purification e-folds — see +`variations` below) and report the relative change of (Δ₁, Δ₂) per knob. θ is perturbed +outward only: inward moves toward the x² ≈ −Q²(G+KF) pseudo-resonance and measures the +perturbed solve, not the baseline. `spread` is the per-parity worst case over all knobs. """ -function delta_convergence(params::GGJParameters, Q::ComplexF64; - verbose::Bool=true, refine_tol::Float64=1e-9, - max_rounds::Int=16, max_cells::Int=12000, kwargs...) - base = solve_ray(params, Q; refine_tol=refine_tol, max_rounds=max_rounds, - max_cells=max_cells, kwargs...) +function delta_convergence(params::GGJParameters, Q::ComplexF64; verbose::Bool=true, kwargs...) + base = solve_ray(params, Q; kwargs...) variations = [ ("θ → 1.2θ", (; θ=(base.θ == 0 ? 0.1 : 1.2 * base.θ))), - ("p → p+4", (; p=base.p + 4)), + ("mesh ×2", (; cfl=base.cfl / 2, min_cells=2 * base.min_cells)), ("kmax+4, S↑", (; kmax=16, smax_tol=1e-10)), - ("refine_tol/10", (; refine_tol=refine_tol / 10)), ("march_rtol/100", (; march_rtol=1e-11)), ("sm_fac 1→1.4", (; sm_fac=1.4)), ("growth 30→45", (; growth=45.0)) @@ -1099,8 +651,7 @@ function delta_convergence(params::GGJParameters, Q::ComplexF64; verbose && @printf(" baseline: Δ₁ = %+.8e %+.8eim, Δ₂ = %+.8e %+.8eim\n", real(base.Δ[1]), imag(base.Δ[1]), real(base.Δ[2]), imag(base.Δ[2])) for (name, kw) in variations - r = solve_ray(params, Q; refine_tol=refine_tol, max_rounds=max_rounds, - max_cells=max_cells, kwargs..., kw...) + r = solve_ray(params, Q; kwargs..., kw...) d1 = abs(r.Δ[1] - base.Δ[1]) / abs(base.Δ[1]) d2 = abs(r.Δ[2] - base.Δ[2]) / abs(base.Δ[2]) spread[1] = max(spread[1], d1) diff --git a/src/InnerLayer/GGJ/RayAsymptotics.jl b/src/InnerLayer/GGJ/RayAsymptotics.jl deleted file mode 100644 index 630d5c397..000000000 --- a/src/InnerLayer/GGJ/RayAsymptotics.jl +++ /dev/null @@ -1,237 +0,0 @@ -# RayAsymptotics.jl -# -# Complex-x extensions of the inps Wasow asymptotic kernel -# (InnerAsymptotics.jl) for the rotated-ray solver (Ray.jl). -# -# The inps construction (GW2020 Eqs. 3–52) depends only on Q — the contour -# enters only through the EVALUATION point. These methods therefore reuse the -# existing, validated `InnerAsymptoticsCache` and coefficient packing verbatim -# and add evaluation at complex x = e^{iθ}s (principal branch of x^r, valid -# for |arg x| < π), the plain-variable conversion used by the ray boundary -# data, the GW2020 Eq. (54) residual along the ray, and the series-radius -# selector `pick_smax` (the ray analog of `pick_xmax`). -# -# The real-x methods of InnerAsymptotics.jl are untouched. - -# Complex-argument Horner evaluator: same contract as _horner(x::Real, ...) -# in InnerAsymptotics.jl, with x^rvec on the principal branch. -function _horner(x::Complex, c::AbstractMatrix{ComplexF64}; - rvec::Union{Nothing,AbstractVector{<:Real}}=nothing, - derivative::Bool=false) - nrows, ncols = size(c) - n = ncols - 1 - - y = Vector{ComplexF64}(undef, nrows) - @inbounds for i in 1:nrows - y[i] = c[i, ncols] - end - @inbounds for k in (n-1):-1:0 - for i in 1:nrows - y[i] = y[i] * x + c[i, k+1] - end - end - - if rvec !== nothing - @inbounds for i in 1:nrows - y[i] *= ComplexF64(x)^rvec[i] - end - end - - if !derivative - return y, nothing - end - - dy = similar(y) - if rvec !== nothing - @inbounds for i in 1:nrows - dy[i] = c[i, ncols] * (rvec[i] + n) - end - @inbounds for k in (n-1):-1:0 - for i in 1:nrows - dy[i] = dy[i] * x + c[i, k+1] * (rvec[i] + k) - end - end - @inbounds for i in 1:nrows - dy[i] = dy[i] * ComplexF64(x)^rvec[i] / x - end - else - @inbounds for i in 1:nrows - dy[i] = c[i, ncols] * n - end - @inbounds for k in (n-1):-1:0 - for i in 1:nrows - dy[i] = dy[i] * x + c[i, k+1] * k - end - end - @inbounds for i in 1:nrows - dy[i] = dy[i] / x - end - end - return y, dy -end - -""" - evaluate_asymptotics(cache, x::Complex; derivative=true, apply_T=true) -> (U, dU) - -Complex-x version of [`evaluate_asymptotics`](@ref) (GW2020 Eq. 53; principal -branch of `x^r`, valid for |arg x| < π). Columns of the 6×2 `U` are the two -power-like solutions in the GW2020 Eq. (2) state convention -`u = (xΨ, Ξ, Υ, (xΨ)'/x, Ξ'/x, Υ'/x)`. -""" -function evaluate_asymptotics(cache::InnerAsymptoticsCache, x::Complex; - derivative::Bool=true, apply_T::Bool=true) - xfac = 1 / (x * x) - R = cache.R - rvec = SVector(-R[1] / 2, -R[1] / 2, -R[2] / 2, -R[2] / 2) - - cc = _pack_y_coefs(cache) - dd = _pack_qp_coefs(cache) - - yy, dyy = _horner(xfac, cc; rvec=rvec, derivative=derivative) - zz, dzz = _horner(xfac, dd; derivative=derivative) - - y = SMatrix{2,2,ComplexF64}(yy[1], yy[2], yy[3], yy[4]) - q = SMatrix{2,2,ComplexF64}(zz[1], zz[2], zz[3], zz[4]) - p21 = SMatrix{4,2,ComplexF64}(zz[5], zz[6], zz[7], zz[8], - zz[9], zz[10], zz[11], zz[12]) - - pp_m = zeros(ComplexF64, 6, 2) - pp_m[1, 1] = 1 - pp_m[2, 2] = 1 - @inbounds for i in 1:4, j in 1:2 - pp_m[i+2, j] = p21[i, j] - end - pp = SMatrix{6,2,ComplexF64}(pp_m) - - smat = @SMatrix ComplexF64[1 0; 0 xfac] - - qsy = q * smat * y - U = pp * qsy - - if derivative - chain = -2 * xfac / x - dy_v = chain .* dyy - dz_v = chain .* dzz - - dy = SMatrix{2,2,ComplexF64}(dy_v[1], dy_v[2], dy_v[3], dy_v[4]) - dq = SMatrix{2,2,ComplexF64}(dz_v[1], dz_v[2], dz_v[3], dz_v[4]) - dp21 = SMatrix{4,2,ComplexF64}(dz_v[5], dz_v[6], dz_v[7], dz_v[8], - dz_v[9], dz_v[10], dz_v[11], dz_v[12]) - - dpp_m = zeros(ComplexF64, 6, 2) - @inbounds for i in 1:4, j in 1:2 - dpp_m[i+2, j] = dp21[i, j] - end - dpp = SMatrix{6,2,ComplexF64}(dpp_m) - - dsmat = @SMatrix ComplexF64[0 0; 0 (-2*xfac/x)] - dqsy = q * smat * dy + q * dsmat * y + dq * smat * y - dU = pp * dqsy + dpp * qsy - - if apply_T - U = cache.T * U - dU = cache.T * dU - end - return U, dU - else - if apply_T - U = cache.T * U - end - return U, nothing - end -end - -""" - physical_ua_dua(cache, x::Number) -> (ua, dua) - -Convert the inps 6×2 basis at (possibly complex) `x` to physical `(Ψ, Ξ, Υ)` -values and x-derivatives, each 3×2 (column 1 = large power solution, 2 = small). -Same map as the deltac `inpso_get_ua/dua` convention. -""" -function physical_ua_dua(cache::InnerAsymptoticsCache, x::Number) - xc = ComplexF64(x) - U, dU = evaluate_asymptotics(cache, xc; derivative=true, apply_T=true) - ua = zeros(ComplexF64, 3, 2) - dua = zeros(ComplexF64, 3, 2) - @inbounds for j in 1:2 - ua[1, j] = U[1, j] / xc - ua[2, j] = U[2, j] - ua[3, j] = U[3, j] - dua[1, j] = U[4, j] - U[1, j] / (xc * xc) - dua[2, j] = U[5, j] * xc - dua[3, j] = U[6, j] * xc - end - return ua, dua -end - -""" - asymptotic_residual(cache, x::Complex) -> SVector{2,Float64} - -GW2020 Eq. (54) residual of the two series columns at complex `x`. -""" -function asymptotic_residual(cache::InnerAsymptoticsCache, x::Complex) - U, dU = evaluate_asymptotics(cache, x; derivative=true, apply_T=false) - - xfac = 1 / (x * x) - M = cache.J[1] - if cache.kmax > 0 - M = M + xfac * cache.J[2] - end - if cache.kmax > 1 - M = M + xfac * xfac * cache.J[3] - end - - matvec1 = dU - matvec2 = -x * (M * U) - matvec0 = matvec1 + matvec2 - - delta = MVector{2,Float64}(0.0, 0.0) - @inbounds for j in 1:2 - n0 = 0.0 - n1 = 0.0 - n2 = 0.0 - for i in 1:6 - n0 = max(n0, abs(matvec0[i, j])) - n1 = max(n1, abs(matvec1[i, j])) - n2 = max(n2, abs(matvec2[i, j])) - end - denom = max(n1, n2) - delta[j] = denom == 0 ? 0.0 : n0 / denom - end - return SVector{2,Float64}(delta) -end - -""" - pick_smax(params, Q; θ=angle(Q)/4, eps=1e-9, kmax=12, cache=nothing, - slogmin=-1.0, slogmax=6.5, dslog=0.01) -> (S, cache, achieved) - -Ray analog of [`pick_xmax`](@ref): the smallest `s` at which the series -residual along `x = e^{iθ}s` drops below `eps`. If never reached, returns the -residual-minimizing `s` with `achieved = false`. -""" -function pick_smax(params::GGJParameters, Q::ComplexF64; - θ::Float64=angle(Q) / 4, eps::Float64=1e-9, kmax::Int=12, - cache::Union{Nothing,InnerAsymptoticsCache}=nothing, - slogmin::Float64=-1.0, slogmax::Float64=6.5, dslog::Float64=0.01) - c = cache === nothing ? build_asymptotics(params, Q; kmax=kmax) : cache - ph = cis(θ) - best_s = 10.0^slogmin - best_r = Inf - slog = slogmin - while slog <= slogmax - s = 10.0^slog - r = maximum(asymptotic_residual(c, ph * s)) - if r < eps - return s, c, true - end - if r < best_r - best_r = r - best_s = s - end - slog += dslog - end - return best_s, c, false -end - -pick_smax(params::GGJParameters, Q::Number; kwargs...) = - pick_smax(params, ComplexF64(Q); kwargs...) diff --git a/test/runtests_innerlayer.jl b/test/runtests_innerlayer.jl index 9aec5395b..8a821f7df 100644 --- a/test/runtests_innerlayer.jl +++ b/test/runtests_innerlayer.jl @@ -52,10 +52,9 @@ const GGJ = IL.GGJ end end -@testset "InnerLayer GGJ :ray backend (rotated-contour collocation)" begin - # The method was validated before landing here: manufactured Δ* to 3e-14, - # Fortran rmatch pins, 96-equilibrium robustness scans to Q = 500i. These - # tests pin the implementation, not the method. +@testset "InnerLayer GGJ :ray backend (rotated contour, Hermite BVP)" begin + # These tests pin the implementation; the method is validated against an independent + # strict reference over the Q plane outside the test suite. p = IL.glasser_wang_2020_eq55() @testset "agrees with :galerkin at the paper point Q = 0.1234" begin @@ -92,13 +91,12 @@ end @testset "InnerLayer GGJ :ray internal machinery" begin p = IL.q4_surface_benchmark() - @testset "cheblobatto nodes and differentiation matrix" begin - t, D = GGJ.cheblobatto(8) - @test length(t) == 9 - @test issorted(t) # ascending, per the reflected convention - @test t[1] ≈ -1 && t[end] ≈ 1 - @test D * ones(9) ≈ zeros(9) atol = 1e-10 # d/dt of a constant is zero - @test D * t ≈ ones(9) atol = 1e-10 # d/dt of the linear function is one + @testset "Hermite BVP resolution floor at small |Q|" begin + # At |Q| ≪ 1 the local WKB rates are small; refining the grid (cfl/8, 2× min_cells) must not move Δ. + Q = 0.01 + 0.0im + r = IL.solve_ray(p, Q) + r2 = IL.solve_ray(p, Q; cfl=0.025, min_cells=2048) + @test maximum(abs.(r2.Δraw .- r.Δraw) ./ abs.(r.Δraw)) < 1e-6 end @testset "ode_matrix: ordinary point and type-generic build" begin From a6e66b51645862f3bbbfe078c2629b3087fa0af9 Mon Sep 17 00:00:00 2001 From: Matthew Pharr Date: Mon, 19 Oct 2026 10:35:21 +0200 Subject: [PATCH 02/12] =?UTF-8?q?InnerLayer.GGJ=20-=20API!=20-=20Take=20bp?= =?UTF-8?q?en=20from=20the=20rotated=20solve=20and=20make=20real-=CF=88=20?= =?UTF-8?q?profiles=20opt-in?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/src/inner_layer.md | 25 +++++++- examples/LAR_resistive_match_test/gpec.toml | 2 +- src/ForceFreeStates/Matching/MatchProblem.jl | 16 ++++- src/ForceFreeStates/Matching/ResonantMatch.jl | 3 +- src/InnerLayer/GGJ/Ray.jl | 63 +++++++++++-------- test/runtests_innerlayer.jl | 15 ++++- 6 files changed, 88 insertions(+), 36 deletions(-) diff --git a/docs/src/inner_layer.md b/docs/src/inner_layer.md index 202c56c10..17e50e8ca 100644 --- a/docs/src/inner_layer.md +++ b/docs/src/inner_layer.md @@ -194,10 +194,20 @@ trusted radius ``S`` can be far outside the BVP domain ``s_m``, so the power-pair data are transported inward from ``S`` to ``s_m`` by an **L-stable 2-stage Radau IIA march** in the quotient modulo the decaying exponential pair — the subspace in which ``\Delta`` is defined (the `GGJ` internal -`march_boundary`). An L-stable implicit method is essential: the decaying pair +`march_boundary`). An implicit method is essential: the decaying pair grows under backward integration, so any explicit marcher is stability-limited -to ``O(\rho S^2)`` steps, while the Radau march *damps* the unresolvable -backward-growing directions instead of amplifying them. +to ``O(\rho S^2)`` steps. The Radau IIA stability function decays as ``2/z`` at +large ``|z|``, so steps that leave the exponential directions unresolved *damp* +them instead of amplifying them, while the slowly varying power pair stays fully +resolved; ``\Delta`` does not depend on the decaying-pair content. Damped steps are +only taken where every growing mode has ``z > 8``, clear of the method's +amplifying window ``0 < z < 6``; nearer ``s_m`` the march resolves the growing +directions and periodically projects out the decaying content. + +The march decides where to switch to resolved steps from the local rates. On the +real axis with imaginary ``Q`` the pseudo-resonance is a turning point where one +rate vanishes, the switch lands on it, and the decaying directions cannot be +identified there; the default ``\theta = \arg(Q)/4`` keeps it off the contour. The damped-zone march runs in `Complex{Double64}` extended precision. At large ``S`` the near-parallel power-pair geometry amplifies the structured backward @@ -210,6 +220,15 @@ on ``[0, s_m]`` and the analytic ``u_\mathrm{small} + \Delta\,u_\mathrm{big}`` representation for ``s \ge S`` share the same power-law tail — the overlap the outer-region matching relies on. +For matching, `solve_inner_profile` returns ``\Delta`` and the layer-center fields +``\Psi(0), \Xi(0)`` from the single rotated solve; ``x = 0`` lies on every contour, +so these are the real-axis values and the penetrated field needs nothing more. +Fields across the layer on the real ``\psi`` axis are opt-in +(`GGJModel(; real_profiles=true)`): they come from an extra ``\theta = 0`` solve, +whose ``\Delta`` is compared against the rotated one (`certΔ`, warned when they +disagree). At large ``|Q|`` near the imaginary axis that real-axis solve can fail +for the turning-point reason above, and the warning says so. + ![Inner-layer fields Ψ, Ξ, Υ on the rotated ray for the q=4 surface at Q = 2i. The BVP solution (solid) joins the asymptotic representation (dashed) seamlessly at the match point S = s_m.](figures/inner_layer/solution_profiles.png) ## Validation and benchmarks diff --git a/examples/LAR_resistive_match_test/gpec.toml b/examples/LAR_resistive_match_test/gpec.toml index 98d9d56a2..1e2bb7ed6 100644 --- a/examples/LAR_resistive_match_test/gpec.toml +++ b/examples/LAR_resistive_match_test/gpec.toml @@ -77,7 +77,7 @@ gal_rpec_flag = true # Append mpert coil-response columns (unit edge s # rational surfaces q = 2 and q = 3: eta=8e-8, rho=3.3e-7 kg/m^3, rotation=1 Hz, Gamma=5/3. gal_match_flag = true # Solve the coil-driven matched xi(psi) from the gal Delta-prime + the inner-layer Delta(Q). Requires gal_rpec_flag = true. gal_ideal_flag = false # true = build the IDEAL solution (skip the inner layer, bare coil columns). false = the resistive matching below. -gal_inner_solver = "ray" # Inner-layer Delta backend: "ray" (rotated-contour collocation, robust at large |Q|) or "galerkin" +gal_inner_solver = "ray" # Inner-layer Delta backend: "ray" (rotated contour, robust at large |Q|) or "galerkin" gal_eta = [8e-8, 8e-8] # Per-surface resistivity eta (core to edge) gal_rho = [3.3e-7, 3.3e-7] # Per-surface mass density rho [kg/m^3] (core to edge) gal_rotation = [1.0, 1.0] # Per-surface rotation frequency f [Hz] (core to edge); forced eigenvalue gamma_s = 2*pi*i*n*f diff --git a/src/ForceFreeStates/Matching/MatchProblem.jl b/src/ForceFreeStates/Matching/MatchProblem.jl index b2aadd42a..a40c5c9f3 100644 --- a/src/ForceFreeStates/Matching/MatchProblem.jl +++ b/src/ForceFreeStates/Matching/MatchProblem.jl @@ -131,6 +131,7 @@ function _compute_match(prob::MatchProblem, model::InnerLayer.GGJModel) inner_bodd = Vector{Vector{ComplexF64}}(undef, msing) # b^ψ from Ψ₁, even inner_beven = Vector{Vector{ComplexF64}}(undef, msing) # b^ψ from Ψ₂, odd inner_params = Vector{InnerLayer.GGJParameters}(undef, msing) + profiles = true for i in 1:msing params = ggj_parameters(sings[i], equil; eta=prob.eta[i], rho=prob.rho[i], gamma=prob.gamma, ising=i) @@ -146,6 +147,11 @@ function _compute_match(prob::MatchProblem, model::InnerLayer.GGJModel) scale = -2π * chi1 * im * nn * sings[i].q1 * inner.dψdx pen[i, 1] = scale * profΨ[1, 1] * resc # X = 0, parity 1 pen[i, 2] = scale * profΨ[1, 2] * resc # parity 2 (Ψ(0) = 0) + # A backend returning only layer-center values (real-ψ profiles not requested) skips the inner profiles. + if length(xg) == 1 + profiles = false + continue + end xvar = xg .* inner.dψdx # X → ψ distance inner_psi[i] = vcat(reverse(sings[i].psifac .- xvar), sings[i].psifac .+ xvar) inner_odd[i] = resc .* vcat(reverse(.-profΞ[:, 1]), profΞ[:, 1]) @@ -163,8 +169,14 @@ function _compute_match(prob::MatchProblem, model::InnerLayer.GGJModel) end # Matched inner ξ_ψ and b^ψ per coil: odd parity × cin[2i], even × cin[2i-1] (match.f intotsol). - inner_xi = [inner_odd[i] * transpose(cin[2i, :]) .+ inner_even[i] * transpose(cin[2i-1, :]) for i in 1:msing] - inner_b = [inner_bodd[i] * transpose(cin[2i, :]) .+ inner_beven[i] * transpose(cin[2i-1, :]) for i in 1:msing] + if profiles + inner_xi = [inner_odd[i] * transpose(cin[2i, :]) .+ inner_even[i] * transpose(cin[2i-1, :]) for i in 1:msing] + inner_b = [inner_bodd[i] * transpose(cin[2i, :]) .+ inner_beven[i] * transpose(cin[2i-1, :]) for i in 1:msing] + else + inner_psi = Vector{Float64}[] + inner_xi = Matrix{ComplexF64}[] + inner_b = Matrix{ComplexF64}[] + end end reconnected_flux = Matrix{ComplexF64}(dp.coil .+ transpose(dp.raw) * cout) diff --git a/src/ForceFreeStates/Matching/ResonantMatch.jl b/src/ForceFreeStates/Matching/ResonantMatch.jl index 2f14fb03a..921095186 100644 --- a/src/ForceFreeStates/Matching/ResonantMatch.jl +++ b/src/ForceFreeStates/Matching/ResonantMatch.jl @@ -16,7 +16,8 @@ fields are empty when the solve kept no Galerkin basis; the inner fields are emp - `bpen`: `(msing, ncoil)` penetrated resonant field at each layer center. - `reconnected_flux`: `(2msing, ncoil)` `Δ_coil + Δ_outᵀ·cout`. - `xi`, `xi_deriv`: `(mpert, ngrid, ncoil)` matched outer ξ and ξ′, one column per coil. - - `inner_psi`, `inner_xi`, `inner_b`: per surface, the inner ψ grid and the composite ξ_ψ and b^ψ on it. + - `inner_psi`, `inner_xi`, `inner_b`: per surface, the inner ψ grid and the composite ξ_ψ and b^ψ on it; empty unless the + inner model returns real-ψ profiles (`GGJModel(; solver=:galerkin)` or `GGJModel(; real_profiles=true)`). - `inner_params`: per-surface `GGJParameters` used. - `model`: the inner-layer model solved, with its backend options. """ diff --git a/src/InnerLayer/GGJ/Ray.jl b/src/InnerLayer/GGJ/Ray.jl index 9261a1027..3010fbead 100644 --- a/src/InnerLayer/GGJ/Ray.jl +++ b/src/InnerLayer/GGJ/Ray.jl @@ -134,17 +134,18 @@ end # projected/continuous-QR variants, whose unprojected stage points # reintroduce the transverse stiffness — is stability-limited to # h ≲ 3/(ρs), i.e. O(ρS²) steps: hopeless at S ~ 10⁵. -# - The system is LINEAR, so we use a stiffly-accurate L-STABLE implicit -# method (2-stage Radau IIA, order 3; one 12×12 solve per step). For -# resolved slow content it is 3rd-order accurate; for the unresolvable -# backward-growing exponential directions |R(z)| < 1 at large |z| — -# the method DAMPS what it cannot resolve instead of amplifying it. -# That is normally an accuracy vice; here it is exactly the required -# behavior, because Δ is defined modulo the decaying pair. +# - The system is LINEAR, so we use an implicit method (2-stage Radau IIA, +# order 3; one 12×12 solve per step) with stability function +# R(z) = 2(3+z)/(z² − 4z + 6) → 2/z as |z| → ∞ in any direction. Resolved +# slow content is integrated to 3rd order; under-resolved exponential +# directions are DAMPED whatever their sign. That is normally an accuracy +# vice; here it is exactly the required behavior, because Δ is defined +# modulo the decaying pair. For a backward-growing mode |R| > 1 on +# 0 < z < 6 (poles at z = 2 ± i√2), so damped steps need z > 8. # - In the partially-resolved band (|z| = ρs·h ≲ 10) genuine backward # growth of rounding-injected decaying-pair content still occurs, so W -# is PURGED against a locally-extracted decaying frame every -# Φ = ∫ρs ds ≈ 8 e-folds. Purging only ever removes span{E} content — +# is PURGED against the decaying frame every `purge_budget` e-folds of +# ∫g_max ds. Purging only ever removes span{E} content — # legitimate by the definition of Δ — so the transported coefficients # of u_small/u_big are exact up to integrator tolerance. @@ -279,9 +280,9 @@ function march_boundary(params::GGJParameters, Q::ComplexF64, θ::Float64, # # damped zone (g_min·c·s > 8 for all growers): h = -c·s. All growing # content — including the O(smax_tol) fast-direction contamination of - # the series data — sits at z ≫ 1 where L-stable Radau DAMPS it - # (|R| ~ 6/z²). Slow-mode global error ≈ 10²c³ → c = (rtol/100)^{1/3}; - # step count ~ ln(S/s_m)/c independent of S. + # the series data — sits at z > 8 where Radau DAMPS it + # (|R| ≈ 2/z). Slow-mode global error ≈ 10²c³ → c = (rtol/100)^{1/3}; + # step count ~ ln(S/s_m)/c, growing only logarithmically with S. # # resolved band (some grower at z ≲ 8): genuine backward growth must be # tracked and removed. h = -min(c·s, 0.3/g_max) keeps z ≤ 0.3 so the @@ -291,6 +292,11 @@ function march_boundary(params::GGJParameters, Q::ComplexF64, θ::Float64, # e^Φ·δ < 0.2 and contamination stays at the rounding floor). The # frame F is carried CONTINUOUSLY with the same Radau steps + QR # (backward-attracting ⇒ self-correcting), so no re-extraction cost. + # + # The band is entered where the slowest grower's rate drops. On the real + # axis with imaginary Q that is the Υ-family turning point x² = −Q²(G+KF), + # where the decaying frame cannot be identified and the march fails; the + # default θ = arg(Q)/4 keeps the turning point off the contour. c = clamp(cbrt(rtol / 100.0), 2e-5, 2e-3) # --- Phase 1: damped zone, W in Double64 (see radau_step_d comment). --- @@ -552,33 +558,36 @@ Rotated-ray backend: converts γ via `inner_Q`, forwards keywords to `solve_ray` pair is ordered `(Δ₁, Δ₂) = (interchange, tearing)`, so the two channels are swapped into the named fields of [`InnerLayerResponse`](@ref). Preferred for |Q| ≳ 1 and near the imaginary axis; use `solve_ray` directly -when the full [`RaySolveResult`](@ref) is wanted. +when the full [`RaySolveResult`](@ref) is wanted. `real_profiles` is a profile-only model +option (see `solve_inner_profile`) and is ignored here. """ -function solve_inner(::_BareGGJ{:ray}, params::GGJParameters, γ::Number; kwargs...) +function solve_inner(::_BareGGJ{:ray}, params::GGJParameters, γ::Number; real_profiles::Bool=false, kwargs...) res = solve_ray(params, inner_Q(params, γ); kwargs...) return InnerLayerResponse(res.Δ[2], res.Δ[1]) end """ solve_inner_profile(::GGJModel{:ray}, params::GGJParameters, γ::Number; - npc=8, certify_rtol=1e-3, kwargs...) + real_profiles=false, 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 of the BVP. The -θ=0-vs-optimal-θ Δ agreement doubles as a runtime certificate (two maximally -different contours through the same entire solutions): the relative mismatch -is returned as `certΔ` and warns above `certify_rtol`. `npc` sets the profile -points per mesh cell; extra keywords forward to both [`solve_ray`](@ref) calls -(θ is fixed by the method — do not pass it). +Rotated-ray implementation of the [`solve_inner_profile`](@ref) interface. `Δ` and the +layer-center fields come from the solve at θ = arg(Q)/4; x = 0 lies on every contour, so +Ψ(0), Ξ(0) there are the real-axis values. By default only those center values are +returned (`x = [0.0]`, one-row `Ψ`, `Ξ`; `certΔ = NaN`), which is all the penetrated field +needs. With `real_profiles = true` the fields across the layer come from an extra θ = 0 +re-solve on the real axis, and the θ = 0 vs θ = arg(Q)/4 Δ agreement is returned as `certΔ` +(a runtime certificate; warns above `certify_rtol`). `npc` sets the profile points per mesh +cell; extra keywords forward to [`solve_ray`](@ref) (θ is fixed by the method — do not pass it). """ function solve_inner_profile(::_BareGGJ{:ray}, params::GGJParameters, γ::Number; - npc::Int=8, certify_rtol::Float64=1e-3, kwargs...) + real_profiles::Bool=false, npc::Int=8, certify_rtol::Float64=1e-3, kwargs...) Q = inner_Q(params, γ) - rr = solve_ray(params, Q; kwargs...) # certified Δ (optimal θ) + rr = solve_ray(params, Q; kwargs...) # Δ and layer-center fields (optimal θ) + if !real_profiles + c = solution_profile(rr; npc=1) # first point is s = 0 + return (; Δ=rr.Δ, x=[0.0], Ψ=c.Ψ[1:1, :], Ξ=c.Ξ[1:1, :], _profile_conversions(params)..., certΔ=NaN) + end r0 = solve_ray(params, Q; θ=0.0, kwargs...) # real-axis profile solve certΔ = abs(r0.Δ[1] - rr.Δ[1]) / max(abs(rr.Δ[1]), 1e-300) certΔ > certify_rtol && @warn "GGJ ray: θ=0 profile solve disagrees with certified Δ" ising = params.ising Q certΔ diff --git a/test/runtests_innerlayer.jl b/test/runtests_innerlayer.jl index 8a821f7df..9dc676329 100644 --- a/test/runtests_innerlayer.jl +++ b/test/runtests_innerlayer.jl @@ -148,7 +148,7 @@ end @testset "solve_inner_profile interface (matching-driver contract)" begin p = IL.glasser_wang_2020_eq55() γ = 0.1234 * GGJ.q0(p) - for model in (IL.GGJModel(; solver=:ray), IL.GGJModel(; solver=:galerkin)) + for model in (IL.GGJModel(; solver=:ray, real_profiles=true), IL.GGJModel(; solver=:galerkin)) prof = IL.solve_inner_profile(model, p, γ) # Δ agrees with the plain matching solve of the same backend (identical solve path). # prof.Δ stays the positional pair (Δ₁, Δ₂) = (interchange, tearing) that feeds deltar. @@ -167,6 +167,17 @@ end @test prof.rescale ≈ (p.v1 / GGJ.x0(p))^(0.5 + GGJ.p1(p)) end # Ray backend certificate: at real Q the optimal contour is θ = 0, so the two solves coincide. - ray = IL.solve_inner_profile(IL.GGJModel(; solver=:ray), p, γ) + ray = IL.solve_inner_profile(IL.GGJModel(; solver=:ray, real_profiles=true), p, γ) @test ray.certΔ < 1e-12 + + # Default :ray returns only the layer-center fields of the rotated solve; x = 0 lies on every + # contour, so they match the θ = 0 real-axis profile at its first point. + γi = 5.0im * GGJ.q0(p) + c = IL.solve_inner_profile(IL.GGJModel(; solver=:ray), p, γi) + full = IL.solve_inner_profile(IL.GGJModel(; solver=:ray, real_profiles=true), p, γi) + @test c.x == [0.0] && size(c.Ψ) == (1, 2) && isnan(c.certΔ) + @test c.Δ == full.Δ + @test c.Ψ[1, 1] ≈ full.Ψ[1, 1] rtol = 1e-6 + @test c.Ξ[1, 2] ≈ full.Ξ[1, 2] rtol = 1e-6 + @test full.certΔ < 1e-5 end From e3954decbcb90144aa03cbc1dcabf741d5a854b0 Mon Sep 17 00:00:00 2001 From: Matthew Pharr Date: Mon, 19 Oct 2026 11:07:30 +0200 Subject: [PATCH 03/12] InnerLayer - REFACTOR! - Remove dead GGJ code and deduplicate the Galerkin and ray solve paths --- src/InnerLayer/GGJ/GGJ.jl | 3 +- src/InnerLayer/GGJ/Galerkin.jl | 128 ++++--------------------- src/InnerLayer/GGJ/InnerAsymptotics.jl | 49 +--------- src/InnerLayer/GGJ/Ray.jl | 112 +++++++--------------- src/InnerLayer/GGJ/Shooting.jl | 11 +-- src/InnerLayer/InnerLayer.jl | 10 +- src/InnerLayer/SLAYER/LayerInputs.jl | 4 +- test/runtests_innerlayer.jl | 5 - 8 files changed, 65 insertions(+), 257 deletions(-) diff --git a/src/InnerLayer/GGJ/GGJ.jl b/src/InnerLayer/GGJ/GGJ.jl index 8bd0488f5..6366f3481 100644 --- a/src/InnerLayer/GGJ/GGJ.jl +++ b/src/InnerLayer/GGJ/GGJ.jl @@ -35,7 +35,6 @@ module GGJ using LinearAlgebra using StaticArrays -using SparseArrays using Random using Printf using DoubleFloats: Double64 @@ -84,7 +83,7 @@ include("Ray.jl") export GGJModel, GGJParameters export mercier_di, mercier_dr, inner_Q, rescale_delta -export build_asymptotics, evaluate_asymptotics, pick_xmax +export build_asymptotics, evaluate_asymptotics export InnerAsymptoticsCache export glasser_wang_2020_eq55 export solve_ray, RaySolveResult, pick_smax, physical_ua_dua diff --git a/src/InnerLayer/GGJ/Galerkin.jl b/src/InnerLayer/GGJ/Galerkin.jl index 8fd490ee5..f7557b609 100644 --- a/src/InnerLayer/GGJ/Galerkin.jl +++ b/src/InnerLayer/GGJ/Galerkin.jl @@ -275,7 +275,7 @@ struct GalerkinWorkspace end function _build_grid_and_workspace(nx::Int, xmax::Float64, dx1::Float64, dx2::Float64, - pfac::Float64, cutoff::Int, nq::Int) + pfac::Float64, cutoff::Int) side = pfac < 1 ? "left" : "right" # Cell types @@ -877,17 +877,11 @@ function _assemble_and_solve_point!(ws::GalerkinWorkspace, params::GGJParameters end # ----------------------------------------------------------------------- -# Top-level Galerkin solver. -# ----------------------------------------------------------------------- - -# ----------------------------------------------------------------------- -# Diagnostic: reconstruct the physical inner-layer field profiles (Ψ, Ξ, Υ) -# from the solved Hermite DOFs over the bulk (Hermite) cells. The thin -# CT_EXT / CT_RES matching cells near xmax are skipped (their solution is -# carried by the asymptotic emap DOF, not the Hermite basis). Returns the -# inner-coordinate grid `x` and the three fields for both parities -# (columns: 1 = odd, 2 = even). Used to diagnose the resonant-layer -# structure vs resistivity. Not part of the production matching path. +# Reconstruct the inner-layer field profiles (Ψ, Ξ, Υ) from the solved +# Hermite DOFs over the bulk (Hermite) cells. The thin CT_EXT / CT_RES +# matching cells near xmax are skipped (their solution is carried by the +# asymptotic emap DOF, not the Hermite basis). Returns the grid `x` and the +# three fields for both parities (columns: 1 = odd, 2 = even). # ----------------------------------------------------------------------- function _solution_profile(ws::GalerkinWorkspace; npc::Int=10) mpert = 3 @@ -930,25 +924,18 @@ function _solution_profile(ws::GalerkinWorkspace; npc::Int=10) return (; x=xs[p], Ψ=Ψ[p, :], Ξ=Ξ[p, :], Υ=Υ[p, :]) end -""" - solve_inner_profile(params::GGJParameters, γ::Number; kwargs...) - -Diagnostic variant of `solve_inner(GGJModel(:galerkin), ...)` that also returns the reconstructed -inner-layer field profiles. Returns `(Δ, Q, profile)` where `profile = (x, Ψ, Ξ, Υ)` (Ψ = inner ξ, -columns odd/even parity). Same numerics/kwargs as `solve_inner`; for investigating resonant-layer -structure vs resistivity, not the production matching path. -""" -function solve_inner_profile(params::GGJParameters, γ::Number; +# Stock Galerkin solve shared by `solve_inner` and `solve_inner_profile`. The matching data are the +# resonant cell's emap DOF, the coefficient of the large resonant solution (GWP2016 Eqs. 34–35), per +# parity isol = 1 (odd), 2 (even); returns them rescaled, with the solved workspace. +function _galerkin_solve(params::GGJParameters, γ::Number; kmax::Int=8, nx::Int=512, nq::Int=4, pfac::Float64=1.0, cutoff::Int=5, xfac::Float64=1.0, tol_res::Float64=1e-5) Q = inner_Q(params, γ) xmax_info = _xmax_3level(params, Q; kmax=kmax, xfac=xfac) - ws = _build_grid_and_workspace(nx, xmax_info.xmax, xmax_info.dx1, xmax_info.dx2, pfac, cutoff, nq) + ws = _build_grid_and_workspace(nx, xmax_info.xmax, xmax_info.dx1, xmax_info.dx2, pfac, cutoff) _assemble_and_solve!(ws, params, Q, xmax_info.cache; nq=nq, tol_res=tol_res) - res_cell = ws.cells[ws.nx] - emap1 = res_cell.emap[1] - Δ = rescale_delta(SVector{2,ComplexF64}(ws.sol[emap1, 2], ws.sol[emap1, 1]), params) - return Δ, Q, _solution_profile(ws), (; xmax=xmax_info.xmax, x0=x0(params), sfac=sfac(params)) + emap1 = ws.cells[ws.nx].emap[1] + return rescale_delta(SVector{2,ComplexF64}(ws.sol[emap1, 1], ws.sol[emap1, 2]), params), ws end """ @@ -960,8 +947,9 @@ real-axis solve, so `Δ` and the profiles come from the same solution. Same numerics/kwargs as `solve_inner(GGJModel(; solver=:galerkin), ...)`. """ function solve_inner_profile(::_BareGGJ{:galerkin}, params::GGJParameters, γ::Number; kwargs...) - Δ, _, prof, _ = solve_inner_profile(params, γ; kwargs...) - return (; Δ=Δ, x=prof.x, Ψ=prof.Ψ, Ξ=prof.Ξ, _profile_conversions(params)...) + Δ, ws = _galerkin_solve(params, γ; kwargs...) + prof = _solution_profile(ws) + return (; Δ=SVector(Δ[2], Δ[1]), x=prof.x, Ψ=prof.Ψ, Ξ=prof.Ξ, _profile_conversions(params)...) end """ @@ -980,85 +968,7 @@ Returns the parity-projected matching data (GWP2016 Eqs. 34–35) with the respectively — no parity swap (see the boundary-condition block above for the parity derivation). """ -function solve_inner(::_BareGGJ{:galerkin}, params::GGJParameters, γ::Number; - kmax::Int=8, nx::Int=512, nq::Int=4, pfac::Float64=1.0, - cutoff::Int=5, xfac::Float64=1.0, tol_res::Float64=1e-5) - Q = inner_Q(params, γ) - - # Build asymptotic cache and determine grid parameters - xmax_info = _xmax_3level(params, Q; kmax=kmax, xfac=xfac) - cache = xmax_info.cache - - # Build grid and workspace - ws = _build_grid_and_workspace(nx, xmax_info.xmax, xmax_info.dx1, xmax_info.dx2, - pfac, cutoff, nq) - - # Assemble and solve - _assemble_and_solve!(ws, params, Q, cache; nq=nq, tol_res=tol_res) - - # Extract the matching data from the resonant cell's emap DOF: the solved - # coefficient of the large resonant solution is Δ for each parity - # (GWP2016 Eqs. 34–35), here columns isol=1 (odd) and isol=2 (even). - res_cell = ws.cells[ws.nx] - emap1 = res_cell.emap[1] - Δ_raw = SVector{2,ComplexF64}(ws.sol[emap1, 1], ws.sol[emap1, 2]) - - # Rescaling is linear & diagonal; apply to the (tearing, interchange) - # pair directly, no parity swap. - Δ_rescaled = rescale_delta(Δ_raw, params) - - return InnerLayerResponse(Δ_rescaled[1], Δ_rescaled[2]) -end - - -# THIS IS AN ATTEMPT AT A CONVERGENCE-GUARDED INNER-LAYER SOLVE. IT PRESENTLY HAS SOME -# ISSUES AND IS NOT RELIABLE IN BROAD SCANS. IT IS LEFT HERE FOR REFERENCE AND MAY BE REWORKED LATER. -""" - solve_inner_converged(::GGJModel{:galerkin}, params::GGJParameters, γ::Number; - rtol=1e-2, max_levels=6, kwargs...) - -> (; delta, converged, err, kmax, xfac, nx, nlevels) - -Convergence-guarded Galerkin solve: jointly refines the three coupled accuracy -knobs (series order `kmax`, asymptotic reach `xfac`, grid `nx` scaled to hold -cells-per-unit-x ≈ `cells_per_unit`) until the per-component relative change -of (Δ₁, Δ₂) drops below `rtol`, or `max_levels` is hit (`converged=false`). -The metric is per real/imag component with a 5% significance floor, so a -converged norm cannot mask a wrong small component. -""" -function solve_inner_converged(model::GGJModel{:galerkin}, params::GGJParameters, γ::Number; - rtol::Float64=1e-2, kmax0::Int=12, xfac0::Float64=1.5, - cells_per_unit::Float64=3.0, nx_min::Int=1024, nx_max::Int=8192, - kmax_step::Int=2, kmax_max::Int=28, xfac_growth::Float64=1.5, - max_levels::Int=6, nq::Int=6, pfac::Float64=1.0, cutoff::Int=8, tol_res::Float64=1e-4) - Q = inner_Q(params, γ) - # nx sized so cells-per-unit-x ≈ cells_per_unit over [0, xmax]; gal_nx must be even. - nx_for(km, xf) = clamp(2 * cld(ceil(Int, cells_per_unit * _xmax_3level(params, Q; kmax=km, xfac=xf).xmax), 2), nx_min, nx_max) - function level(km, xf) - nx = nx_for(km, xf) - return solve_inner(model, params, γ; kmax=km, nx=nx, nq=nq, pfac=pfac, cutoff=cutoff, xfac=xf, tol_res=tol_res), nx - end - # Per real/imag component relative change with a significance floor (5% of |Δᵢ|). - function comperr(a, b) - e = 0.0 - for i in 1:2 - fl = 0.05 * abs(b[i]) - e = max(e, abs(real(a[i]) - real(b[i])) / (abs(real(b[i])) + fl)) - e = max(e, abs(imag(a[i]) - imag(b[i])) / (abs(imag(b[i])) + fl)) - end - return e - end - - kmax = kmax0 - xfac = xfac0 - Δ, nx = level(kmax, xfac) - err = Inf - for ℓ in 1:max_levels - kmax = min(kmax + kmax_step, kmax_max) - xfac *= xfac_growth - Δnew, nx = level(kmax, xfac) - err = comperr(Δnew, Δ) - Δ = Δnew - err < rtol && return (; delta=Δ, converged=true, err=err, kmax=kmax, xfac=xfac, nx=nx, nlevels=ℓ) - end - return (; delta=Δ, converged=false, err=err, kmax=kmax, xfac=xfac, nx=nx, nlevels=max_levels) +function solve_inner(::_BareGGJ{:galerkin}, params::GGJParameters, γ::Number; kwargs...) + Δ, _ = _galerkin_solve(params, γ; kwargs...) + return InnerLayerResponse(Δ[1], Δ[2]) end diff --git a/src/InnerLayer/GGJ/InnerAsymptotics.jl b/src/InnerLayer/GGJ/InnerAsymptotics.jl index 127ccaa14..7fa947160 100644 --- a/src/InnerLayer/GGJ/InnerAsymptotics.jl +++ b/src/InnerLayer/GGJ/InnerAsymptotics.jl @@ -20,12 +20,6 @@ using LinearAlgebra using StaticArrays -# Index ranges that partition the 6-component first-order system into the -# 2-dimensional algebraic ("small") subspace and the 4-dimensional -# exponential ("large") subspace. -const _R1 = SVector(1, 2) -const _R2 = SVector(3, 4, 5, 6) - """ InnerAsymptoticsCache @@ -68,9 +62,6 @@ struct InnerAsymptoticsCache Z::Vector{SMatrix{2,2,ComplexF64,4}} # k = 0..kmax end -# Helpers for cache indexing using physical (zero-based) order k. -@inline _at(v::Vector, k::Int) = v[k+1] - # ----------------------------------------------------------------------- # Build T, Tinv, A_0..A_2, J_0..J_2. The coefficient matrices A₀,A₁,A₂ are # GW2020 Eqs. (3)–(5); the Jordan basis T, T⁻¹ are Eqs. (7)–(8); λ = Q^{-1/2} @@ -353,7 +344,7 @@ end Construct the `inps` Wasow asymptotic basis (GW2020 Eqs. 7–53), truncating each power series at order `kmax`. Evaluate with [`evaluate_asymptotics`](@ref); -pick a cutoff with [`pick_xmax`](@ref). +pick a matching radius with [`pick_smax`](@ref). """ function build_asymptotics(params::GGJParameters, Q::ComplexF64; kmax::Int=8) p1v = p1(params) @@ -642,46 +633,12 @@ function asymptotic_residual(cache::InnerAsymptoticsCache, x::Number) return SVector{2,Float64}(delta) end -""" - pick_xmax(params, Q; eps=1e-7, kmax=8, xlogmin=-1.0, xlogmax=4.0, dxlog=0.01) -> (x_max, cache) - -Sweep `x` log-uniformly upward from `10^xlogmin` and return the smallest -`x` at which `max(asymptotic_residual(cache, x)) < eps` — the cutoff `x_max` -where the GW2020 Eq. (54) convergence measure drops below tolerance -(GW2020 Sec. III, Fig. 3). Also returns the `InnerAsymptoticsCache` it built -so callers can reuse it. - -Throws an `ErrorException` if no `x` in the sweep range achieves the -target tolerance. -""" -function pick_xmax(params::GGJParameters, Q::ComplexF64; - eps::Float64=1e-7, kmax::Int=8, - xlogmin::Float64=-1.0, xlogmax::Float64=4.0, - dxlog::Float64=0.01) - cache = build_asymptotics(params, Q; kmax=kmax) - dxfac = 10.0^dxlog - xlog = xlogmin - x = 10.0^xlog - while xlog <= xlogmax - delta = asymptotic_residual(cache, x) - if maximum(delta) < eps - return x, cache - end - xlog += dxlog - x *= dxfac - end - error("pick_xmax: failed to reach residual < $eps for x in [10^$xlogmin, 10^$xlogmax]") -end - -pick_xmax(params::GGJParameters, Q::Number; kwargs...) = - pick_xmax(params, ComplexF64(Q); kwargs...) - """ pick_smax(params, Q; θ=angle(Q)/4, eps=1e-9, kmax=12, cache=nothing, slogmin=-1.0, slogmax=6.5, dslog=0.01) -> (S, cache, achieved) -Rotated-contour analog of [`pick_xmax`](@ref): the smallest `s` at which the series -residual along `x = e^{iθ}s` drops below `eps`. If never reached, returns the +Sweep `s` log-uniformly upward and return the smallest `s` at which the series residual +(GW2020 Eq. 54) along `x = e^{iθ}s` drops below `eps`. If never reached, returns the residual-minimizing `s` with `achieved = false`. """ function pick_smax(params::GGJParameters, Q::ComplexF64; diff --git a/src/InnerLayer/GGJ/Ray.jl b/src/InnerLayer/GGJ/Ray.jl index 3010fbead..57684ace2 100644 --- a/src/InnerLayer/GGJ/Ray.jl +++ b/src/InnerLayer/GGJ/Ray.jl @@ -11,15 +11,7 @@ # the quotient modulo the decaying exponential pair (damped zone in Complex{Double64}). # On [0, s_m] the stock Hermite-cubic Galerkin assembly (Galerkin.jl) solves the BVP with # parity conditions at the origin and v(s_m) = Us + Δ·Ub + c₁E₁ + c₂E₂ at the far end. -# -# File layout: -# 1. system — plain-variable first-order ODE matrix (used by the march), parity sets -# 2. mesh — WKB-graded Hermite grid on [0, s_m] -# 3. boundary — decaying pair, Radau IIA quotient march -# 4. solve — driver, profiles, convergence battery -# system.jl -# # The GGJ inner-region equations (GWP2016 Eq. 11 ≡ GW2020 Eq. 1) as a plain # first-order system in v = (Ψ, Ξ, Υ, Ψ', Ξ', Υ'), dv/dx = M(x)·v. # All coefficients are POLYNOMIAL in x, so x = 0 is an ordinary point (the @@ -78,18 +70,6 @@ function ode_matrix(::Type{CT}, p::GGJParameters, Q::Number, x::Number) where {C return SMatrix{6,6,CT}(m) end -""" - parity_rows(isol) -> SVector{3,Int} - -Component indices of `v = (Ψ, Ξ, Υ, Ψ', Ξ', Υ')` that vanish at s = 0 for -each parity solution, mirroring deltac_set_boundary: - - - `isol = 1` ("odd"): Ψ'(0) = 0, Ξ(0) = 0, Υ(0) = 0 → components (4, 2, 3) - - `isol = 2` ("even"): Ψ(0) = 0, Ξ'(0) = 0, Υ'(0) = 0 → components (1, 5, 6) -""" -parity_rows(isol::Int) = isol == 1 ? SVector(4, 2, 3) : SVector(1, 5, 6) -# mesh.jl - """ ray_breaks(params, Q, θ, S; cfl=0.2, min_cells=1024) -> Vector{Float64} @@ -114,8 +94,7 @@ function ray_breaks(params::GGJParameters, Q::ComplexF64, θ::Float64, S::Float6 end return breaks end -# boundary.jl -# + # Large-s boundary data at the matching point on the ray x = e^{iθ}s. # # The admissible (bounded-as-s→∞) solution space is spanned by @@ -149,6 +128,15 @@ end # legitimate by the definition of Δ — so the transported coefficients # of u_small/u_big are exact up to integrator tolerance. +# Small and large power-like solutions at x as 6-component states (Ψ, Ξ, Υ, Ψ', Ξ', Υ'). +function _power_states(cache::InnerAsymptoticsCache, x::Number) + ua, dua = physical_ua_dua(cache, x) + return vcat(ua[:, 2], dua[:, 2]), vcat(ua[:, 1], dua[:, 1]) +end + +# Condition number of the column-normalized boundary basis [Us, Ub, E]. +_basis_cond(Us, Ub, E) = cond(hcat(Us ./ norm(Us), Ub ./ norm(Ub), E)) + """ decaying_pair(params, Q, θ, S; growth=30.0, seed=20260707, dp_res=20.0) -> E (6×2) @@ -236,18 +224,20 @@ function march_boundary(params::GGJParameters, Q::ComplexF64, θ::Float64, return Floc end - I6 = Matrix{ComplexF64}(I, 6, 6) - # One Radau IIA step: A = [5/12 -1/12; 3/4 1/4], c = (1/3, 1), b = A[2,:]. - function radau_step(s, W, h) - M1 = 𝔐(s + h / 3) - M2 = 𝔐(s + h) - Ablk = [I6-(5h/12)*M1 (h/12)*M1; -(3h / 4)*M2 I6-(h/4)*M2] - rhs = [M1 * W; M2 * W] - K = Ablk \ rhs - return W + h * ((3 / 4) * @view(K[1:6, :]) + (1 / 4) * @view(K[7:12, :])) + # One Radau IIA step in the precision of W (`Mfun` returns the matrix in that precision): + # A = [5/12 -1/12; 3/4 1/4], c = (1/3, 1), b = A[2,:]. + function radau_step(Mfun, s, W, h) + CT = eltype(W) + hc = real(CT)(h) + Id = Matrix{CT}(I, 6, 6) + M1 = Mfun(s + h / 3) + M2 = Mfun(s + h) + Ablk = [Id-(5hc/12)*M1 (hc/12)*M1; -(3hc / 4)*M2 Id-(hc/4)*M2] + K = Ablk \ [M1 * W; M2 * W] + return W + hc * ((CT(3) / 4) * @view(K[1:6, :]) + (CT(1) / 4) * @view(K[7:12, :])) end - # Extended-precision (Double64) Radau step for the damped-zone W march. + # Extended precision (Double64) for the damped-zone W march. # At z = ρ·c·s² ≫ 1 the step matrices have cond ~ z and the LU backward # error has a SYSTEMATIC direction set by the elimination structure — it # does not dither away, accumulating a relative error Σ eps·z ≈ eps·ρS²/2 @@ -260,17 +250,7 @@ function march_boundary(params::GGJParameters, Q::ComplexF64, θ::Float64, # band stays Float64 (z ≤ ztrk there, solves well-conditioned). CTd = Complex{Double64} phd = CTd(cos(Double64(θ)), sin(Double64(θ))) - I6d = Matrix{CTd}(I, 6, 6) 𝔐d(s) = phd * Matrix(ode_matrix(CTd, params, Q, phd * Double64(s))) - function radau_step_d(s, Wd, h) - hd = Double64(h) - M1 = 𝔐d(s + h / 3) - M2 = 𝔐d(s + h) - Ablk = [I6d-(5hd/12)*M1 (hd/12)*M1; -(3hd / 4)*M2 I6d-(hd/4)*M2] - rhs = [M1 * Wd; M2 * Wd] - K = Ablk \ rhs - return Wd + hd * ((CTd(3) / 4) * K[1:6, :] + (CTd(1) / 4) * K[7:12, :]) - end # --- Schedule: geometric where damped, growth-capped where resolved. --- # No adaptive controller (three generations died on estimator artifacts); @@ -299,7 +279,7 @@ function march_boundary(params::GGJParameters, Q::ComplexF64, θ::Float64, # default θ = arg(Q)/4 keeps the turning point off the contour. c = clamp(cbrt(rtol / 100.0), 2e-5, 2e-3) - # --- Phase 1: damped zone, W in Double64 (see radau_step_d comment). --- + # --- Phase 1: damped zone, W in Double64 (see the Double64 comment above). --- # First purge (at S) and all damped-zone steps run in extended precision; # on resolved-band entry W drops back to Float64 for phase 2. Wd = CTd.(W) @@ -318,7 +298,7 @@ function march_boundary(params::GGJParameters, Q::ComplexF64, θ::Float64, end (isfinite(gmin) && gmin * c * s < 8.0) && break # resolved-band entry h = -min(c * s, s - s_m) - Wd = radau_step_d(s, Wd, h) + Wd = radau_step(𝔐d, s, Wd, h) s += h nstep += 1 nstep > 5_000_000 && error("march_boundary: step limit exceeded (s=$s)") @@ -350,9 +330,9 @@ function march_boundary(params::GGJParameters, Q::ComplexF64, θ::Float64, have_F = true Φ = 0.0 end - W = radau_step(s, W, h) + W = radau_step(𝔐, s, W, h) if have_F - F = radau_step(s, F, h) + F = radau_step(𝔐, s, F, h) F = Matrix(qr(F).Q) Φ += gmax * abs(h) if Φ > purge_budget @@ -395,20 +375,11 @@ the column-normalized basis. function boundary_basis(params::GGJParameters, Q::ComplexF64, cache::InnerAsymptoticsCache, θ::Float64, S::Float64; growth::Float64=30.0, seed::Int=20260707, dp_res::Float64=20.0) - xS = cis(θ) * S - ua, dua = physical_ua_dua(cache, xS) - Ub = ComplexF64[ua[1, 1], ua[2, 1], ua[3, 1], dua[1, 1], dua[2, 1], dua[3, 1]] - Us = ComplexF64[ua[1, 2], ua[2, 2], ua[3, 2], dua[1, 2], dua[2, 2], dua[3, 2]] + Us, Ub = _power_states(cache, cis(θ) * S) E = decaying_pair(params, Q, θ, S; growth=growth, seed=seed, dp_res=dp_res) - - Bmat = hcat(Us ./ norm(Us), Ub ./ norm(Ub), E) - cond_est = cond(Bmat) - return Us, Ub, E, cond_est + return Us, Ub, E, _basis_cond(Us, Ub, E) end - -# solve.jl -# # Driver: series radius S, BVP edge s_m, march S → s_m, then the Hermite Galerkin BVP on # [0, s_m] with the far-field state v(s_m) = Us + Δ·Ub + c₁E₁ + c₂E₂ (Galerkin.jl, # `_assemble_and_solve_point!`). @@ -447,10 +418,6 @@ struct RaySolveResult ws::GalerkinWorkspace end -# ----------------------------------------------------------------------- -# Driver. -# ----------------------------------------------------------------------- - """ solve_ray(params::GGJParameters, Q; θ=angle(Q)/4, kmax=12, S=nothing, smax_tol=1e-9, cfl=0.2, min_cells=1024, nq=6, verbose=false, kwargs...) -> RaySolveResult @@ -469,7 +436,6 @@ function solve_ray(params::GGJParameters, Q::ComplexF64; cfl::Float64=0.2, min_cells::Int=1024, nq::Int=6, seed::Int=20260707, ztrk::Float64=0.3, purge_budget::Float64=2.5, dp_res::Float64=20.0, handoff::Union{Nothing,NTuple{2,Vector{ComplexF64}}}=nothing, - boundary::Union{Nothing,Tuple{Vector{ComplexF64},Vector{ComplexF64},Matrix{ComplexF64}}}=nothing, verbose::Bool=false) cache = build_asymptotics(params, Q; kmax=kmax) @@ -504,28 +470,14 @@ function solve_ray(params::GGJParameters, Q::ComplexF64; end local Us, Ub, E, bc_cond, Sbvp - if boundary !== nothing - # diagnostic: externally supplied boundary data (Us, Ub, E) at s_m, - # e.g. from an extended-precision march - Us, Ub, E = boundary - Sbvp = s_m - bc_cond = cond(hcat(Us ./ norm(Us), Ub ./ norm(Ub), E)) - elseif s_m < 0.98 * Sv - local UsS, UbS - if handoff === nothing - ua, dua = physical_ua_dua(cache, cis(θ) * Sv) - UbS = ComplexF64[ua[1, 1], ua[2, 1], ua[3, 1], dua[1, 1], dua[2, 1], dua[3, 1]] - UsS = ComplexF64[ua[1, 2], ua[2, 2], ua[3, 2], dua[1, 2], dua[2, 2], dua[3, 2]] - else - # diagnostic: externally supplied series hand-off (Us, Ub) at - # x = e^{iθ}S, e.g. evaluated in extended precision - UsS, UbS = handoff - end + if s_m < 0.98 * Sv + # `handoff` is a diagnostic: externally supplied series data (Us, Ub) at x = e^{iθ}S. + UsS, UbS = handoff === nothing ? _power_states(cache, cis(θ) * Sv) : handoff Us, Ub, E = march_boundary(params, Q, θ, Sv, s_m, UsS, UbS; rtol=march_rtol, growth=growth, seed=seed, ztrk=ztrk, purge_budget=purge_budget, dp_res=dp_res) Sbvp = s_m - bc_cond = cond(hcat(Us ./ norm(Us), Ub ./ norm(Ub), E)) + bc_cond = _basis_cond(Us, Ub, E) verbose && @printf(" march: S=%.4g → s_m=%.4g, bc_cond=%.1e\n", Sv, s_m, bc_cond) else Us, Ub, E, bc_cond = boundary_basis(params, Q, cache, θ, Sv; diff --git a/src/InnerLayer/GGJ/Shooting.jl b/src/InnerLayer/GGJ/Shooting.jl index b83b2c369..9bb00b054 100644 --- a/src/InnerLayer/GGJ/Shooting.jl +++ b/src/InnerLayer/GGJ/Shooting.jl @@ -1,9 +1,7 @@ # Shooting.jl # -# NOTE: This solver is NOT used in production and is not to be used. It was a -# porting exercise retained for reference only. The Galerkin solver -# (Galerkin.jl) is the sole supported GGJ inner-layer solver; shooting underflows -# at large |γ| and shares none of the production matching path. Do not call it. +# Valid only for |Q| ≪ 1 (it underflows at large |γ|); the default GGJ backend is `:ray` +# (Ray.jl). Kept as a cheap model for tests and backend comparisons. # # Stable backward shooting solver for the GGJ inner-layer model. # Integrates the 4×4 origin-diagonalized @@ -12,10 +10,9 @@ # Frobenius basis at the origin and reads off the parity-projected # matching data. # -# This solves the same inner-region equations as the production Galerkin path +# This solves the same inner-region equations as the Galerkin-based backends # (GWP2016 Eq. 11 ≡ GW2020 Eq. 1) but by a different numerical method: a -# backward shoot in the origin-diagonalized basis rather than the matched -# singular-Galerkin weak form. The 4 origin Frobenius exponents are +# backward shoot in the origin-diagonalized basis rather than a weak form. The 4 origin Frobenius exponents are # `al0 = (p1, 1/2, −p1, −1/2)` where `p1 = √(−D_I)` (Mercier-stable required; # D_I = E+F+H−1/4, GWP2016 Eq. A9). The two "small" (singular) modes are # columns 3 and 4 (`x^{−p1}` and `x^{−1/2}`); the two "large" (smooth) modes diff --git a/src/InnerLayer/InnerLayer.jl b/src/InnerLayer/InnerLayer.jl index 7f47632e6..a2ec7adbc 100644 --- a/src/InnerLayer/InnerLayer.jl +++ b/src/InnerLayer/InnerLayer.jl @@ -1,9 +1,8 @@ # InnerLayer.jl # # Resistive inner-layer models for matched-asymptotic resistive/extended MHD stability. -# Provides an abstract `InnerLayerModel` interface and the GGJ (Glasser–Greene– -# Johnson) submodule. Future submodules (SLAYER, other inner layers) will plug in via the -# same interface. +# Provides an abstract `InnerLayerModel` interface and its implementations: the GGJ +# (Glasser–Greene–Johnson) and SLAYER submodules. module InnerLayer @@ -16,10 +15,9 @@ include("InnerLayerInterface.jl") include("GGJ/GGJ.jl") include("SLAYER/SLAYER.jl") -import .GGJ: GGJModel, GGJParameters, build_asymptotics, evaluate_asymptotics, pick_xmax +import .GGJ: GGJModel, GGJParameters, build_asymptotics, evaluate_asymptotics import .GGJ: InnerAsymptoticsCache, mercier_di, mercier_dr, inner_Q, rescale_delta import .GGJ: glasser_wang_2020_eq55 -import .GGJ: solve_inner_converged # experimental, not exported (reachable as a qualified call only) import .GGJ: solve_ray, RaySolveResult, pick_smax, physical_ua_dua import .GGJ: delta_convergence, solution_profile, asymptotic_profile, q4_surface_benchmark @@ -37,7 +35,7 @@ model_name(::SLAYERModel{S}) where {S} = "slayer_$S" export InnerLayerModel, InnerLayerParameters, InnerLayerResponse, solve_inner, solve_inner_profile export GGJ, GGJModel, GGJParameters -export build_asymptotics, evaluate_asymptotics, pick_xmax, InnerAsymptoticsCache +export build_asymptotics, evaluate_asymptotics, InnerAsymptoticsCache export mercier_di, mercier_dr, inner_Q, rescale_delta export glasser_wang_2020_eq55 export solve_ray, RaySolveResult, pick_smax, physical_ua_dua diff --git a/src/InnerLayer/SLAYER/LayerInputs.jl b/src/InnerLayer/SLAYER/LayerInputs.jl index 949f02963..e909e68b1 100644 --- a/src/InnerLayer/SLAYER/LayerInputs.jl +++ b/src/InnerLayer/SLAYER/LayerInputs.jl @@ -23,8 +23,8 @@ using FastInterpolations: DerivOp, integrate, cubic_interp, cumulative_integrate Minor radius at normalized flux `psi` and poloidal angle `theta`, computed from `equil.rzphi_rsquared` as `√((R − R₀)² + (Z − Z₀)²)`. -`theta = 0.0` (outboard midplane) is the default; pass `θ = π` to measure -the inboard side if you want an average. +`theta` is normalized to [0, 1): `0.0` (outboard midplane) is the default and +`0.5` is the inboard midplane. """ function surface_minor_radius(equil, psi::Real; theta::Real=0.0) r_sq = equil.rzphi_rsquared((Float64(psi), Float64(theta))) diff --git a/test/runtests_innerlayer.jl b/test/runtests_innerlayer.jl index 9dc676329..17dc3323e 100644 --- a/test/runtests_innerlayer.jl +++ b/test/runtests_innerlayer.jl @@ -110,11 +110,6 @@ end @test ComplexF64.(Md) ≈ GGJ.ode_matrix(p, Q, 0.3) rtol = 1e-12 end - @testset "parity_rows match the deltac boundary convention" begin - @test GGJ.parity_rows(1) == [4, 2, 3] # odd: Ψ'(0)=Ξ(0)=Υ(0)=0 - @test GGJ.parity_rows(2) == [1, 5, 6] # even: Ψ(0)=Ξ'(0)=Υ'(0)=0 - end - @testset "decaying_pair is an orthonormal 6×2 frame" begin Q = 5.0im θ = angle(Q) / 4 From 09bac85724af2aab4e98f6d8f6042a086cd127a3 Mon Sep 17 00:00:00 2001 From: Matthew Pharr Date: Mon, 19 Oct 2026 12:50:22 +0200 Subject: [PATCH 04/12] =?UTF-8?q?InnerLayer=20-=20API!=20-=20Order=20every?= =?UTF-8?q?=20parity=20pair=20as=20(=CE=94=E2=82=8A,=20=CE=94=E2=82=8B)=20?= =?UTF-8?q?=3D=20(interchange,=20tearing)=20and=20name=20parity=20by=20the?= =?UTF-8?q?=20displacement?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../inner_layer/convergence_Sinvariance.png | Bin 51521 -> 51966 bytes .../make_convergence_Sinvariance.jl | 12 ++--- docs/src/figures/manifest.toml | 4 +- docs/src/inner_layer.md | 35 ++++++++------ regression-harness/cases/ggj_ray_q500i.toml | 30 ++++++------ regression-harness/cases/ggj_reference.toml | 28 +++++------ regression-harness/src/runner.jl | 24 ++++------ src/ForceFreeStates/Matching/MatchProblem.jl | 26 +++++------ src/ForceFreeStates/Matching/ResonantMatch.jl | 8 ++-- src/InnerLayer/GGJ/GGJ.jl | 5 +- src/InnerLayer/GGJ/Galerkin.jl | 44 ++++++++---------- src/InnerLayer/GGJ/Ray.jl | 30 ++++++------ src/InnerLayer/GGJ/Shooting.jl | 13 ++---- src/InnerLayer/InnerLayerInterface.jl | 25 +++++----- src/InnerLayer/SLAYER/Riccati.jl | 2 +- src/Tearing/Dispersion/CoupledFullMatch.jl | 2 +- src/Tearing/Runner/run_slayer.jl | 2 +- test/runtests_innerlayer.jl | 12 ++--- 18 files changed, 148 insertions(+), 154 deletions(-) diff --git a/docs/src/figures/inner_layer/convergence_Sinvariance.png b/docs/src/figures/inner_layer/convergence_Sinvariance.png index 861e993c4af375105ceb9d8cb7a00060ab91f968..094e9737066b08e8d6c505f4a150e6cad93aee65 100644 GIT binary patch literal 51966 zcmb5WcRZHu|37{jAv+{1R6-#|nHfbXNh*o#2xYIxmXVoCvR4BYAsLlDQ)WgaTTv7h zvVEUd-S5v|zkhz${dnB>{orz4=XspR@p?ViafE7Vsxi=V(Gmo~aQv9+8G@kLPY~oh zH01b6Zk$&u{zG-~gqkX`PWmUUEHj!Q_=)4HhqT?3rjjiU&NhB%5ZZWP)=0(vdK!)J z?vrGjYwN`}$cUqm-DK zBahC!eED(%C1vm{`BeY9i=V%I`7$=PH(ulP>2^iY6DLj-Jb(W2<3|Aj0bFfg@$&q4 zI$GKUDO;{BTRsr4P8%7OUwX%GWMt&(I!9)+Cgx{2GCInwXvno+H^ew}X=!Pz{8eFL z;h|QtbLYCem*)>0IKbdK&Ague_;F)hUC^y z^~jR{rDR}eNJjkp`BSC;Ht(@x#|WaNq=ep8t$f?%%a;!yK1>jbii-R8z~C;X+S;lrldDH}{ReK(FvG9uKmzvKkulBO>TC9bH^r zWMl|hNM4=ldGTVuW#NP3oh}Z`9RmZ3Za+R{WeH2fPks4fVP)0R-=7>8 z$HB|1XxWnFI@!IrwB&SC%3Hp+wzjAKWF7u(V^r$C&wI&*+<#_yx?=L%H$edbN-8SN zg#EjA?b?{zqpq%=ot^#U>C-Kux+a$|$H&Iv8(zjsS}J-iIN+M&dVBKC>gwvKrEKmc zBzTP0N1jZSYJBsC-sE>~dO?A6VOZ>V}A)($Khj z>lQ&I$v9qg(4S(Eak994xwn`zpsKB-gMwK3-KwNJ>`y^W5EZNQ+yn3H>NXI0nDW_U z!!HwywMTUh{|a($dl=Pt;GI zJgK2E)&JTJYd}M=qqde($>EHFfq}mM($c9$&USXs9zJ~d{JGP$Ym1`| zQQTZy`wtw*JegQuQ&aPD5VIjw!Bgk->23V{X&D(7c6KfA-i1p~{P=M*JpA3;w-@(v zBqStscXzKkZhiOWP1}bLd`dnCy)H6v2u8;zB_-Xvhu;Z`h{)T0lF=NG=u-i7F$?Y7;YU?aJz^|xczO_?UB3+3C^d=J^wJS zZw{zBcJgF%OH0O?$9St*!_BP+uCVp#=;`TUJW-e|B;xb)^JQga-@kv~($a!2PF3{2 zbL*DY>C;sa61lW8=n+(}NY$Q&V?iV=+*rC=7`w zO-)U4oiXY$ckU$YzsypueZ|0 zEEvIs=y~qb1_s&p?_a!pd2wa&w_=k~na3qegxp;86VL2hM;|o4dnbM107ks3qdY(V z^o0uviHWc8-zQhnw6U;Y=i}q!Du&w zf>a{b2H!#Vz5DmObZ6@s4~{sPS`}^^S#Im^XAu9`)6=uob6#6JE-`VmmDSXASmgY( zA=@I`J}QESp57qOglxcRp!AxH+}4i<<5yaFYh$&RIj*OE%Q!3`>0^xOU8ynlZyX&O{ZXdhB#238P^Y<499g672 zgDw-y@f!8T7p<+s`EG`VhLRDY`bA9*4bgjRz8O_bknokylgwPBKjehOO zv^jN>Ht5&4uBWZM*PlJxgNMz_n}U_m%Jrunz(Ce8?`MF%_HNhr505X{qtmyhDn;d* zPY;w4ez-T$3omHwzfMeqls%buKUM1Tm1U)A0M9u9T_I}@VakPQ-Pkm zBL0@0sB9RwfUbEwSYBVn%+~n4yu6YUcPA$awpnJ0c(3&}?)t;{HjJP3`quf_MkP_paHoKP$#rF8; zZGUYYo%z$2o}RDKxOn!4M@3N+8Yu@~PTP5H;^pNf{64>n{bNB4?yhJZ(o<4v8G3Ys zk13!jMS+`eSY2{mu-Db)AS&zYgPW&@sse^8J}morw+y)!`>y*GImsoLU+LPtvTOgf zUt@lL1flF}K(BPd&8_(M?b~1p}p^*<;i?GEY$xP4SY{1^y!% zSl4IH{95=qN_yNOA#WNRFI!u8w6zgL_JzW4H8+^hXJhvmvaqw?i;bmT_a2z;EubdS z9zAkJ+ihxUI-hG)mG41EM@JPvW{WF3eR>lMi`>;I-7{y-XlO*l#B3%^=BIiWjLA}! z^NOaXrrf3nFu8g^egpuzs1$wUhMJbvOk28&!@{?T_6J^GUYJgJL#hHZIt>|NWo`Z8 z!w28)xM*OgZQHhy`{#MgeG3c>{PgJ)rVADi>+270SFax4HZnAXmOP0W{VrBqB{w!L zjX#@rAyDfa>BT@#uW|Au10y4F4He<;>8X;4f>iRuvn5G(-#U4rjhY(u-A$+g*E2iN z%!bKLSH8|3`8zx)AANnxb>Ul>cn_K+KB}HLo%HkfZ}gaw*RLCDYXx@hyyoG-LPLpW zXEWd2(2&_6bU!hXySx=wJ3l{v=+GgIac^&L6tBYb!onaW){4!YX8>_f28-^c;%w=wF4pdh8`jECZ+d)1#dHLlmR*yt6!&hu;bP5-L|N6D`#@5(r@yY9iZOGL!%7h{+t#=pf>XhlT4^a;vYxc$Y?Z(|6;*VlK! z{>&Mc((1mxzJ1(+(Xwb%D-_&el0+qD(9gnTMQ<(#8B-wB!)7+WOG^*3gg(s5dXwSG zvvn)(?ycYgYo)ImC;Ex1swxQtQqw0zX`MOqBq!&)qqIbP)9D9CH_-$(MDdNj!?+U! zaOk9?NW}B!5;jXsot-ZLG3`Ay(e}v+u&!^-#C+|WH(9S=bBjcTg!n}<*l5#-NuEA^ zdUs4%JeDCDA*h)Y5;Ob7`RbP@PNEWv_GjkVW5;N;D|<+jHA0ymbH?i`)2wg{(V(@5 z=SHPwJ31jK6b5m{4#Z{?8{3#yb0x*#uZ@(49Ub@S(3}g8kLO$)FIXzRP!L6n6?M~> z(e~qujfBI>f@3!2+ibcmduDZHc?R-|iyJ<4eEj$XL(tH0-q5hWFBlgkz!Dl8Tbz|e zBa)qy6ZE@tVU)b#`%O+#C_Hc;ldT=3m8z2mEci;%Q*u{5`gUdGd>eQF9o zR%v`zSFX(W^Vt+;04m(Q%eJB+z!J4pK3F>7!AC3)i@uea;TpnkvxrWmZ@SJvku7(k zo{P(Vq7txCgfmYj;Km)>WD8qcF+c%var@)PH|ppb88P-t&5Y2e*rZuqZ+0GMRN(DV6L^3>7TZ1HA_6F@oy0a}ce702nX>{oLcb$)?eNHgh; zlo~rPFC)>DXG&4t*4xYJEO7l(>9y!8lWfD+_iT@|CGneC*S&c|b5le)Fes=Yl3Oja z11Ky1BSD}SSU7jqEX)k6cz7%UnWP=7o|&0pW@Ziv3;X6Ma!gIFVfJf>5*QI05;gUW z+FDgl&*koJouZ`))$QQZJVb@a1B{jET+DS3|_+d3|8yj8mza zkIw9iXCz9T$2G03pB5BICaP@X-Lq$p%va#;rrwcQkHuNTZ9FqIYeC~2^Q_Mc3eKK6 z15&Z1E4WeoRkFO>$mAwwW(PO7%yz3&sfyoiYx45;QUwf8P0_2J+6H);C+2>}dso}^ zNj%iw8F-@*GYxLD`kGHtGxR8)R1g9kUMOqDy3-b?^H09V`3JPTd2}Bu>m98yHvV}!P zP|yaQH($#H#Ka8GoO!SR*}IthR3=(F$a=n6gHI8Q)XccDo0~KbM?D9~S7w7Wm6DQD z;@N`-pD&!P>+e_CzkfeJKk@rvu>F>qlN37y1;1blgUEdT{CPhYgGeq4=YtyWwsqRx zmQzKkw^C9V2@VAh7e4=OLyOnOTedFP1&|eg7h~Q+41po0WlHj;M8?O*m)Z7E1BYD7 z*9G&83p{uFbo^e^!(Lu11(vNgHa1jRLcBIdXgc>PklROR9;08BiKzvhz2_~y_hH9Z z?>9R10P8L1@>A;?8^7jOtX*HLViuMe>f4bL98Bd$7uKD)$DiA&UUT^js4D(iUQRAf zLvYQGzLnDE0(-#kd!WpRADvO^yM@y8sR%M0R-eOhnfab4&z?~cFA57cv#~iiJCEL& ztgH|kXubQLDzw0uoRyW;$Y=mX1XyQoUk?Qk?-e^c@biVsbTiYQi$sf$o12@sc<$5l zxptpQHnp%n&dM56yEMdn0R+&O>a+|s1#lN64ag2X-A8n^wTIS&B)LFT92^`L-ltY> z)b;`TaS$UH%9BMUn-H8kVsfZur~*9(SPTyV6&aJ;=!Mm39i48l&LwxDU`ejLlmTWI zmM4!NW3X&?U#+BmRjf0V6aU?@uABB?cHDf>tmV<8T3XD(F4cYmLdFzZw!}g_!PG@N zJD;tKa$IRHG3=yt%+2l3{P(^_bEhj;cKc}LmzVP@iFNr>6<7Q4u4ZIppyic!kj<5B zBm92r(Vd`j_=wxNd-rZ!TwGqH_#WLn6OaSQW+-dMxqE?Hz(2UQZjE$1Z!(DjB$mg> z4XEcm;X@AH;p&F<4{x2W$7Pt@4OjlAZ*og(B{Qn!fM@7Iu)cHW`W8z}K##=yI^IbpTruP{ z(nq5RXlT$UYyO#;sk9bVQKU zii$p3wejicrr>Y5Dx*u!IpGGdKcX-HoSBhvk%!P<@UG zSX{c)ZuMfI`bi{@>~oNqojW)9E?ea5&M5m{=2GRj8t5FMcIs5_{rlVT8}SyIQ$jMI zo3HBM_$}y7v9+K)>*=Z~Ku@M-GA#{_Zn@VrJnt=AwkUql0se#bi6Y)-GY#HI-Ti4u zho-d*0(DV3qg0}0YYK^LpDkXcR2SB?JT$=}?Kc(w;h7-?QCXMg4vdSY?*l1Jzu2zo z^jL0HP0fz|`)462kf77}r_alOruh^+RJY$=x|uDwef#sP-#@k%b+yLJv?vk;8yj1m z3RF9v*@Hkp{5jJ>}dgQ5u5l+MH51EVh!5ypB#y zWg5&ZD=n4zz}?W$VD@fk_!!fyZv#E1IvMfp+qa(kk`wBXr^Sk%;M!1ZdT33PxutBN z95&pL4yf!(V58ko!OMI&vm<|Jl0%_jksr?}$Q40|iHUi6XiXXU8Rx)g*eNJj&sl%H z%EW}MD^JGKMrx*+Nne=uTWCr_k zD3YlRHx$h3>D$IVq-A2wp)auG$CjR^AA=Q49v3WWSI11& z^Jgq>0S}V%KP_%l>X-QmntI;hiQ6@tJ5y~71+%pb4ZTe^A6DD9(sDy2+1uOO zvrl$rB8pr3rsOVDPfvNDN4ufsUIO*T{9c&Mdi9FyX8fbfOtYX>y&OHL#dy`#b(z&4 zb(czri!<5j=;(;0p#h=!K?|?xUJi#tSvfgk`ak@kcy8Kp)X!+Ugb$sJug!@QbO+6$ zR8-TVL_<`CA*9$LT*`2hTbi*#)+@Y*y5D_$O#$@^4}XnUVyG)&@A$61ubpjeK)bCq zH37yu^v;|i_a36!*}|EksAFASECWTp%GS{e3xCV@-MeWu`MEebljU5$q1l70V-hAy zT%z??uB_f}GMtOKy*Abu4H^jqu#uJ)gx)K=MV!TQ?+~ZU-TddzN2a)4)E;OF!xqBW z0X4ry^+%CJhse8OZ9ft*XU|Us@~+@HpLFor`}%q+DqU(qKuE~UVlV%#7cXW3kzhtF zt*tHt$HT9B{N%~NYd5BkvuBg?*CLxU?%#J>{Ph`9n2>uDK~u zIyXv47&_v+cLC1KXqGcFM~@t_?R|c!CYYfu4RGe!_c%G%D?mv{j|S)F=AsW`MAY~v zGi9u8ZG%ob`>wD4k+f_vD0K%vj}m1E&}U^FQ!bWW`3mDH*w*OGnd*iH=xtYje8T0w z!>DM+OKi~G#t~Xo$~VX zOlgNT9Z};<%L@X(_vBL;*#YsiK$vlx<~6ukVBW}5s^?qF$@UqLMcWOYPjIgsp?~&! z$ZPJpqa9pI6%`d{Cns2NnU5ZAXn0eRDHAZ93gL^YxGsGI@I^Q#Ata!JW*0z@)E!@;(39Ni~S$*Ip4>xLqfY z{5Nmjm^gZPK7iE%LElF0ZEfusMA5>+!kLZVM@HVeX%EBcEb0zb-R?u(-PM(U@)rq{ zZcXzElVlH{8>*sMc|m?}TbfcPD~gumD3y=px5-JB;ydYomlToKFk^wr@BYCFiXJ>Q z^jbgvu!7vjx3C;^vvG@gvfCUS9fx-eLEQuYc;4(0ee5A5&0$Grhia3(=q^F2hj!dP zHrbtH#@+lqN@h8mPLxt!Zsx!gW|((pFEuU}H*2mRQq#~d{`qs)pQkND67~ZJTLz&j z_L;TySFEpb`$hn}^i&@`%&X`X@~33v%NIq6>xs>Nb)4aK64KJ+!^5U@lURh(wjTp4 zPD02ttnk_DW$Z}B>deqrT0=qcxqD?Z$k_2?$FiP0+0IPEMtcb|e$q>EG6EwC{|z_< zG?1O0J&AL-siw5(cB+RDUlv)+{x1vgFtEzR!D7k!%9ZPrp>QQU^&i2@NP&f;t9wj< z1r=8{rh*kMh1vk zN(ygzF)jcO%EHjC9!=}Zmv6_$T6)GE*uTHjV~+MqH)`nKefx$D7$5>HqM*SPgZ2T_ zZl78GtmLwRrJ@pW>sDLbKC_`QI+DZ5@XB(Ru<-1rYji~A#e7(1c;TyYt*{kk zw*2&7n*9oy`}_Cr@Eza3zhmo$FT@Lxf&99V-C|LtC&&P&^(e`bE z_yE5bn)AZ>AhPp4U0vsNbOibNE9Xb5%q7mAJqz3Z_3PK4$HpKZ%YKNIl9DR-S$*~J zVW5WKyT-;yPRWdE2Nn)oC#j(hTQ)a0|BT)3GmYXt&)yzTcX3Wg8+Jle6w^(yUAuQn z#A{5Lbfz+RJ_H}Zasu&%Gl!aKXJ=OqhsgI}H}&l&Po7{6>YP8{VYMF>hLts1@p(eE zOXb|$94ud4LD}k6uE=?GD=3MmevQ#W&K?c1ckjAfy?VvUYIc*^BWdX3qhn((&UqbDJUq+%tp~fT2Wzte`%iSx|rwp$G0W=ppcN7nwljFcpJrVCRwOtZEGW{ z4(3~hqN5DCKZl^#((L8hkWC8T0?4A{;z&l~4zn7AO(DFd`MMZfj3G2%?+Rw09gf}H zKYsjxW8c`)VnO%p=Ys$VN`4=zn>@1Q-Z9X2 z+_iEjRj@P;z`TRff=+fQdr>GrnV(1gYD9Q=xY(7SZRF1JFs}ayowXo>-Yc*0?3b42 zQ}p7<*b@wG%;=@lXMIXNL|#;?VJOHxX!TWKWMm9rF&fXbtPb3`+O%h>{}xP?2L}Dx*5k%f1sK8*!7{{ z>4zP!b;CumhSvIgd9CVY-S%jomvY0!g-VmXP}?4RZc?fKV8DecWnhr{b76faJ0+?p zuBxgPEDj3{22jAA@3;_~{#VF*Y*`c8xwC7%G845$SpC~x|Dz88RK4e~9P;A(-$z5P zJc)R#bYIP<=yLOT zYwGye81fNF#oTH%x3;zhm1Saz+M#wcN#4z_GwU=67s7z(Tx|K0_mHr z^y*lXu54tB>WLE~($a2Op8gB*kS;6#KGavCfRGmM2);Y`b4<{`h9gKh@s;Xcs@ZQh_ z$}c+u07ytkpa&1W*i2GoA%RK6uXrbLv$VbVH>~T(x`{a$dkl3K)Qja#o)0Q+`hEF= z`=e{8j^4kwtb3vlW?7Xjq{^0o0l?=odV0M*JrJlkmv`^ndBo6g6{zj2uPr1pScH`1 zWP}4;fXd2B#RzXNFVrULPtI?U>KYvxDSv)vjdjx|$C;t3>F!Ur{Eq&6L<>w+Rc^eG zwiIW3(}a{{3iww_ByDUYa-Th0JFvRml5Ozv%*m6ss4IZ;q&VOP zF4@16VMK}Nplimp`l@wdN&2l%1rNQ&^rOmu384w}7s%7TuPEo)vzs?=P~UTNarsp4 zEe}ZsUNgpaHTydh1<3F-zhM!WoF5$>1&PPfMzRfH0)7XQdR~i8nBibj$w^7P2i*w* zIY878Nhv9e7;-@YF)*)pOGv!0s;cVlW+$K|EBdZ^VH!Y~eE3kn>a3pLOOq;cG($1{ zA{RF|3W5|K%GQ(gfe=30Fx~$;_UMB{@1S8SUHfJJ_Uy4k6FKmDxlw> z#}as zVDtz-q)680J{Z5g`dtnIJRhHOH16c&evCbYop<;oZv1@qmFpxVJ}AwrtE*&$p`js| z8HN&8HgGQFGXHxd<@4vyMa1`zNn8WZurN0#2nfJzuykOrfAPc)$Sx6t|C+ zB7g{`l3nb=-T3&8BAjptGP-=!|0^IPzAw-N=t2ncbZLrvY34^<`}vDXE_Y<$R^#L1 zY(AB=cXa%Q7nry5vCvxU2)xt9o2lR z3=4aEPfQ==ZLqz48={4=bXh3MAt96-Hs~SIhy*2cT)^lfM>hNx=qvYrjoZ6%W%@H*86WF+`3vrx43$Otc3^?%c-*CgTGcz=djKRjIh3{g(b3cBq;U07T zTSaTvnc3MhiVu*nvod?|R`9>j+N?%@A$Sf6uc;{;=spX%>FL{ChQ)X94vUJa@LrZ8 zD&M{h0}&Mzw7>&zo9fQd?<=xp-Ll2 z1#A9CKb`mbHa6NvPo9L;U364`!Fz<;U)cmoX#tuvI&@UIL624v(q-__eSJPWIuZM& zCE0U!;xti-+5!<_c`sU~sIV}}t%AFz@C0(Jpdg9G_d1uxE${kY7h1VdQDn!)*vB}L zoMgP|J>T2B1OR>N{FeyjfX5eO5#d>)FyQGUOF1|=_~wo9oH6P=hy}DpQltzSN)eH# z6x57Rhgfo(2m26;lvkEqmHd)VLgxs#Snczze7Wfk7x*=u==9KPD#9 zI=+I{Ic%jM_+@2#Q6N$)eyUOa*9_Nc=&7m4cd-VxG!tDiF*OgJ%SuIk?9aN-%<(3_ zqH2Qd8FTmU(I{S9RLmbg%3Z#`XW~@Ziqn6duN(3dYa!@_p&+J#~Qa)z8aM)! zfzf^eb?4Uowk|VXr91Zg;eMJIU!GmpMnF5UfYbM2}mkLDr4i#5A*VF)m=nQ z^={X}*W-mbzq$|2B>0{7CPIwnFI>E@1|uv}H(vbgmS1h>OYAb;ekZl2Q!G~;QPJMr z1$!PZ6%{l12I#Oo=MmB`*wxiKdmAHy;WHM9C@m`kCTHsJGA?z$oszOPr+|sM{G;EP=i^BP=IbLk(Jhvj7+0?R zuiE)$J$qIpm0F_ueLaSAtnaHNG8gsrN1+a59iw5GZWKWcGqHP%#SX-guXHY7SJc;c z{o3y@WCTojUYOor-|vI~636lc+D={AW~8RUvFd;A0)Ycuw7PuxWXi!sV3j-sR6F0j zvjz-4)*SSb_RQI{5Q07Dr}VHVV0^IfCvy6JQXG7 zY~~ZtV}$=FzFaahlf3+10QT+B(9ododUBPCMzS0l%N&LkK_n0jt(lEf>U zD+`NG&V@qDR$dMDo4g9IpmjZbXwK~RA(vpW{6~AEYN(mCXtpN3rQcrr&b3p+b=^Mz z0oS|>D9lLEw&9k}KQnk~+b1QOqNqROESJ32`vlcy?DJ>S8Kj6vFQ~jwt;xvz;bdd| zKD$sDrp%9YdsD&zk^TGGh`qR5odjK^#iYTu(rpD|PSnLz;paYVm3^zmE;?SBmGr&8%np6|EPR#uB% zG}wz=uzH#@X7Ia$N~O z&!i>H@V8>DQO9fC47n!J-@P=-%_|n-Di5VnlQQkiF_jA%8RaW)`c2fMg2-pkqgNvar zdbnZ7(TJhXpM%y+2?7NW2~%hlC>e;h!fFIw0E8|oEK~qI#-CvX0obs0qQAc%Geh&l z32xICZ=eHi8~^cR?Q4h7)~(6#bZnPnpcV!OHQbD0d|}m&rZ!w*-JN|q zI$FQNrz|y<4em+ z@rZUuoBFY15nJWiMT+zC5HBMLgAxZ*z&&(lP$_3Ow}wxhKL*MsfBaC)@|=t%b}Fv# z)*AVpN^y6=OV@u-i)i_g5oZE{k;JlQbK9de9q)s8lv|FsICFhks@Q-s{{HRG%B-fK6sEC>Rt1i6sH7cab8k3uNCWMVQjF_8rb_Vg*;hkfYQAh9bvZ>Qt~f@%M% z6cd}VeDkszQj57YBfwVVizkMM_W@G=L$4ZUQc>`u@HdqP1!dzQ80)ph{^RrE3Z1pR~N4>#5SDwYjM5+fhucX{Wx8p93vnF1p!SF^BJxf3K)FyVI62E zn41?$9I$D~3rNS@{2{<4(6zt+AuB5@b@jK%lf%z~Rw27X4+b4$myY6;Jc?LFM@Ka9)!KdVR(yk>pC1yT z{y8VGC^s+1@(OWoq$IcS+fa&O>CZC_xOwv?*cF6z%e`T5-e8BKBNS|+GHkO5p5@R` zd~xxgC+D7uiiwdCFzC)Q`uN^z{fl3GH037vpWkg#=xoryO-&s!e{=MU$q8&G z+{N}5!aC+LoMhB^8Pn=O+$B4Ta3CS znKptUuzvaYQXvLF;T~oQ+IYUyUlw))c*N2!EyZXw{zs4G~^$Nh#5R6&?yMiJ0FeBrF zt}ba~T5WCThYzF;qo}p+?m*8cJKmCI!mb`ntc1$ zXKu)xyxlf>?~a#3CQ)2e1lh#<&yQr}f&&6-uyPRLx3sbn78Nzn)y2OfKC_)aeHxN& zP^zi0FF}N=(lRkYft!I#2n7PT142e*t`c@{eoKU|3=t$YCdTw4-5FzJ;97T70%%9% z{?O8UvH4C+Y%AjDqoV~*pVjH;!jU|M?D6ZDlfAvYjo@kYj_<_>-Di}wv>ZN_I1&Vq zsnXg4g@wG|AQd&WuTGMwD{x_s;cG}*Nhgya;~-U5T?W~VWRXGcMN?x5B|RGx3uxsC z2=0~LMexJfQdj?m<`Z`a{wU8jJXR-H*P#1X5m7^s&il`d{C~v8=fd3$p4}>`NA6}? zw$JN@P^P_2?^&t`jVdbYM#=m>;L55gq34mZFFw zV+G*X5C>s%O`|R$iov}7YhgaTl>$SKIkaBzzTBJFOP3ia+96cE8^Y&C{%iM3%8wi{1!Vw{?o z!1cVYo2IzH>_=i|wOWU_-xd`WeP&cfyCMGN%WL>ntU@vZ0;Hrx6Y|3S17WSPENldf+6x!Yf%BO2wCi%s3!aOqXq! z5r~AOV3RFecckto^y7in_5ihGlNbyt>_Wyv@c#@Hirz)|K^wpeqX|n6{ThM5RMqXM z6teR2p6>3z{#_qFRCp~)2nq)0d_mp-g39;7ii#I6T#z(i71U^Z|DK#cfFDz08V)z` z6zaa^Z*3R=Z~hTv6&RIt$(lC`T!FH|dgG*ZwY1u9Zk30iHhl0we*Qi}Sw)3H?iU4d zOyGU^7NL4|ivMK+#L)&`y?zZ7owTEih?8~xg86}dD9rX2X{{Msa2}|9*a+B+Pev{R z3??330^#m}fB;`3F5?wcbJUigp}PUVL`znNFrEtv_aKU!*NMT zHkU5Bg3fsjqo~7sK%IPa2A_%ByS%BZ}iX19FOFdhI$Vw$@mVcA(SJ;c3xq@ zqUwI{Ef_CIUg=J&9XH;f?zQIZ$CAnr(vL~m9Qu#Trbgo77^BQ)T~P8~+V8LIj?HL9k;2s}4l*@_3KGep z8x4x>lCg^k!ap|rV!p z-3u5%tI!8P+dl;FR?5(T_0-u$mn|~NzdiE?yz)z|YhQvW? ztzp-XgtMQ1jGfr#rBzTN)K8rFN#=QjmQDU|hgK5GZn-)CLS{yGdi$NY{ev`SMb#~z zTs%%LT5|ETEHX5Om>=@uEGT?DT4UXIHg5MGy-P+16mH6efM#GrNwSi!4-R&KyM~Q* zLMIbQ%NK2cf?(fckoELwVruF-QdR&v*zXRAgzb%(C%Z&Nr_kNNt+5OD#Ia)>vQFk` zz%lAzFc+Xh;~)$SkIZXyolqzo=zmaEQJbp#7NE?NtlN>1U-R=uMK--aLHOh%`$6Q` z($mtAt?ValK!KO0js{T!h80xv$BGw!L>wk8p^(_gF~8@Fr?@O2H+!;PCbG^ za55p`0^lLG7w-$eP`@fEp`l$H_ha1nZ$*uaKP=e$beIpxklTT^V~i^`Iz0}5M3a}U zSqhRf@m-79T>fy>+e;&4jk_#dQ~ z=H|{J&qlujOs)sKrgb7eQl)I(9{$u z6)5G1P?{^MBsTaGeu;^FxPl7pq-NC6ukRlLjp4aLEx8*LWBAf(=YR>e!eENy2ox+U zxMPTc;ldH=M*Yq*llcqYebO$I{6E zf9mQ=(#%(m##PsVBh%mdA_Ror>IoP0#!cqM~wawoq3O!|4iTWo0*RG~jWeCIQ@HM9?1d-80!}cVc6Z4`%BPz7W-m7z7kv zIHXwPXc#y67|4l(*b@dWO%Q-Zh?;`sW;N{vktLx!$a5EKY2bQcdi)J~J%&G(gflWQ z-LYW_Qijgivrn_LOPxN`!YTU1e8SAn5l;~vG_KwRI2LQE_3hjDU0vTjPmSP+i5q+< z?H{uBSUEWx1zQl3!j}1=@o{Wq!)DNLAm$Grg6`DU)fFON*<^zX=OTwfz`B;0lCnok zEb>o{wUyPa+qbLM%3LS!0m5nYDvteQ;UTH)caF7sOcXG?FO&$3QT1fS&2H%h{~{rc zmrix4Ui$j4k%0pK{L+g$XLIEWcsll2lM~1go4le;UGM@X0I2vnHHA@`$vBw^h=R2g zbR-;|Rq!6=Mv?}y^mA0L)WicqEcV44^g})ijX6b13U@vRjYj4Eh+c|T4~hpsVlwD4 z1`9GSHWAjXeZ}gR>1khl3-(FEDyw$F#`d8~|Fx-j=%E@kBS;QkZ~TBGEO6j}Fk2Wh zeb`$8*|g`mD#qnvDmEsgxtomq1}{gNz)S8iRwrpAjZ)bXXwQWCyfUhOypMrd3R>;acB6aWa=y`f*U z0%$-|JUcr94{=aUow$rJPOd=yGe5uTy>+!$8c8)MymC(IPd$VH7)N3|cg_KeVZ~8W zQ`b0ITTj9Xg94OZUap8DU~Ie&9e{)uoyKTFRdIR+Ca#04D{SzryLUTrNk}u6l_`{4 zfLOwM#YslU+btm96)kwO`si2E=EAdQYjDa)Z=*c}i>1QMw=NM-QV0=ejASxLa*MMx1C8W>;~H)M?TNPmAaDJRU<7-S&EXT$&&@Z+YalJEWow%Q4uv)l8QF{$87r!{T~xFbF)nQJKp6pL#%R@i z#7O=5-bYR7zP_3R+K)guP8|WRyMH8n=78m;OU*cJ31taJwFn|@t9S+Y!td zTxDWnB6{-lrN$_6jkO^$7w#VUcMw9h4W8izmF~0d{XuUrS^jmi^~5SZRQZ;yW0{Q zVEru4ens~@2mIUB^*Q3*ukUYKT5uSVe7P!uE-340)SH=^c^ArTUIjNh#5;p zAhhm=XOfd+YiG9y8X81!5Zn)csQ(gw%KPi|{xZ&2uilJ|TwVP$h+qT&6YBn96%~}- z%lkiKD9baxeEMX7*cAjt(8M1<>@>cSa2(7G=;S!12Eqz%7$7Jq5sR__QF+%r9)PHf&BgW1o6V^T<{4h_7sEj&>3M6}oB*2m zY~Ui?_4=dFDrbv{{Ln`o^CcyOE}%m%d&49a{z`(1zH>SY%IJw5fBv>g%erq6Q@`A zL+2hDA75YixkKM357riT9r%VX*kjfL{OPipKrcdrVbuAIJQbX&eS7!%tz(mt*Xf~X zzMXz;rP(<4>_$5oxOj^R^;>qvh$>`(_HtHsZww}z3ItchJ}SW#aTJFTMN%U)p_cw z?^aks&G<=XH_dhO``ek#Dap-+TEjaMskgIC(~heydK)j?o{X4eYLs3495ES!%T>e~ zUU2Q)Cc7hujigge{ z%!uiDRrQ#efGN=k#tO!&tUz|ha1UBN$= z$g*Jh(J?XQhTp_ni2)v!;cOg9guNy?lSZ9a=8%N}z^B=Uj)q`6pR^s%k<+O@OJ6^| zbPhT^j7b9BAs_F4^^6jKJ~VhO^O;}wl|tle1OstA)@NXSw)vae_f#9dITL&9=koZE49ZS7x27pBg{F=~UPCP|Z zN%4mCz4UpkEl^*8^kSoQjchHpXAY9b>UYOvcJ(@G|zK^DoF+d5BI(c5pslOhPCdKVdp zS)&dzxFY&LbokMXj)`2-%U7?;Ar1`sEQ_Udl4i<`L`JS`$Cbj1`R)MR2#TSGxi~mv z#Ra~``3gvY(O9Cj3kE`4*(&Ff^-JJW&PM#W(nW@qh7z!r-i>sE;!KgrQi3F=e01ZJ zWaL=iI_$$wiHzXCPl$@1Bkjy%`j3d_N!#@74Gt%L@ZJNM40~b|laf~2)%ec&ICQKo z|G{kxkB-*-@2`U#uz>UNa~zl#Vn@=xkW&GY0xE3$zxP;LgRnVasX&wiIl}=CNPo=! z`h_fQAlUcsI?|QIv1LRhk&f%?&NWs7=t7`YRz?PKp7#h|#i*0sqCu;o)`IGW*Y0AM z=>cze9jNWF=)BQ$u^lL?!MZJtOmgn;=LrT^_o5!d^L(0&%~VI%8)|AsVW>29{+$;I z9JH1y!St7LAXD@25Y_D#VSn#g4;2Jy(8@|>izU)IlkT4R&MKtOBedy;>G7Y+K>j4s zJL8xGB}qSKz3xDoiYABS7%hS3*p7e&M-BUs-ZDU|p`?#PJzkAKC)#@m$QW|Ag5!_F zI#-|NM3z{;&bz%sZNE*=t?#dhZ*;i*12{fSKwu0TqyA2aT(b{9`gsQ;EpmIE<6e|( z-oF@eveo|P038kE;#9bJ;RUh2F0xKK4L;e9$vNZ=lBMm9pjqK$LiFZ30R-waljZi2 zR;;#ep+|G+g#G5|tG5OFMYuK_3Px|?oRo_4xSQhWzRnwVUpJdMO)+iOLm_(gvG#8K z=@p@}$kuLpIy!w2b1SQf3SAw+Xk_uaJdV$Z3$xMkMm3D?TQ%J9BK^ls$`5l965ZDj|Dsl@&>nkPxy%WQ2?oB3rVuDm#0Z@jdT7 z-|x@y`Tp|#1HO*e@j9OInD_hbcDt_Yyw3ByM*2COW;V~Z^<=$D4l;H*l*{+W8q zS8!X?VtF6kjPs?etjQrsj{&`*WXd8xcU!d+DvX?RpIFVi?J_ewi+aP8Mdv=P-1yy6 zrs|c=6*F90`1&N#9=)OWKz0UzF5)J9I+nr|mECq};a)Kc*72*iz^qVifd8 zGi+L_h%|WK%9NRw@y6o|p`*`UunVY(ls-$@vnAX`g(xN>u5}@TzRqwi(u|c z@2l#0gT(>qeAQy@lg`F#ieH<87$&rmRHB~Cm8YNTpuf@lMA6fH0owU(seuBacrSTrhX2z1-{_Z`2ZJ&!}OX=(u%){`A;&;kzTQls_zlADhnFT$) zM9cT{NnDT3WQOjL%|MQ&p5JW8O_>X3k&598K~IgV`7=LuUgDyCtk-SVkZyTqf_b#j zWa6sq(?7K(4>C(a)%b41SyI;jZOz$rjY4}(BQG|^t8+$-mB9hlep>luKev0{ zrRJhzIWiG(Z1kaSNZZG|e{!P+qYbM0Efk7Ecj)EU^gT6PYq*x;b|>c11+qbF3O%FW zIl<~$bZ&Qot3MxirgZy#)8LTR306AGTS&y_Fd7aP4c2l0|{QCCG zl}o`%t+sWP{d_|V9{=XgQR)DW`kID9j&ll}caGdVTcZ+0qvI(r)vx zwwu*nDuIs;)%b6|SID=d^*g00e&xhBI{Lq2!*()Jnu-_I%o;sPJBD1M2CdS+KCzF| zwLJOa#!P_h<@yYPTj8bZDf@~BCzR9K$Ig~kcScJlvx|tI>6|vH)17G2dUbY9KIkc1 z>8F*UoP_Zu6VqeAZbXGj3)67Am`1zKx>}LOMO5!-9hK31urcHmv1N<@XMR^h^`VFc zmr}tCOII1wv@;YV#=@&5LNZq`CLSk^SeH1_Zt{7-c8B8hz|A~!asQN-wfWevv@5O; zW`kAJGH$VYtT9-T20o79wTyrADuRA+^{$9;YybAo}` zz6U;ohJDnQWX^&Eek5V{T3>nG z6^D$F321sn)`K5Gi$++12$!onn$PqJVR2>ldjUb<>z17B-_vz2j}ON_zvcSuWvy2r zc_Ya(dXLK0% ziD(~KJDlTid`P*m^6I@W<%_@j9F`0AzZ>4=z2&6#79c&}kW0G3ey_NgmX1yk94a(3 zKn(!D_g_+UfFn?oW<4$^@$yFTY@v~fr*r7>oLpKbvyS2WtUE=Vrs^FXNEUaH51u@7 z1gc`2^*@V%9&phC4FM5&F5-}$lyr;;+umFB^!g8cd6rcX^OoeKfyr+Y)J5p$5^bOG zJ|YIn(VA})y~6ec1u**jsI@@?22rDc>tD2GI_bk3CATzN!whQ>t(3nePqpu!pTR!? z^i%9!0=N5UbHESHw76t3dVg8h#(1u4nhm6SfeuNoJdI8KG+MvIZgNYYg6jL-T_{QFd# z$a}oJyh3Fb=JszzLI`*U6cPF?B9*Rq#lzGHGcGiSgpvB7xEoz`l?qVL5C`S$g|Hp6 zm!?4;o&U0A0}+a}_Hm@I=iHWFqtAmh7!pVh8mhx$*SW$QpYvz5c;T|1(Wb{Mdvogl z@goULfHuLvUI4d`^uLUR$ifbX6dF{L`ib&$q5>!61uhcYqQ^U0KCrwu>N#U{312Wr zhYl|ixn28bRcgDr=d9VU<;AS|l+2R;J<%S0Y14%@`xthTdacKe2C|@tCwVDhG&w8J zJ^|zvjXS8;KyJ)08P48#J1`R5bAVT2@3i`X;6R12fL|?&<&<7)zs9B}waf}((Lmxn zG4T1u0hAI~pPf`nQ$;)5de7Za$EGEa8rW6R{X8o9a_H|I!3$sn(w@$WxE z_!fcWoEolx%Qax}$yNwiIF@!lS_t?Px)|oiUf}*h1;xl1T{p5bU(-Ta`3Zn3RPAtn z!Phu(`s2@8G8Ujz4bS=C=H#&WP(iqaq|Q7x5D(PQY>&l1rUp`-9@HeEyX-nRQS+ zQttzhkDuu16JfQ0I#q)%zd_fN#ziq8_jPjAf@{P4&R_=q^vwVHR`x=mj{`Gu1ICXY zr`PIG1iHqkQ*WA>z$$L3K?5J93}p{cT82E}g6{y&A>X^Apil;w6u4-H&UY}OunloG zjCW-BL$7l9(4n>AV=dS??$O&rdv=;X=Nx+fIFX!^GV_1m_q%BWnlqMNxkEq#pMDtv zY@!EH8wVhCK4v-OxTHW;&;X#%Lshbj*0>Kfy7jp5M3KV9mEO&tXWlUdkSn|2=+>=a z?=9esZCOu@i|a@8K0Sulwa;Y#xu`_4Df!ni8BwoK?q^#2ozXM``gXbJ^ffIAmP2Y1 zn=H3Y0A;dn%6(8_ZXohh_L#KN0cOF9EWs{5AF2435XNDNVAtg-;3DGq(f}1f6+Zhd zTb1h+?o;O*mi0v71*as`dMhi909rujlLtbWa ztaI^9(OTL&Rt0rsk-sd{A1qy` zK)>$4839Kb!Pw^np9t6sz;i9ss92C#&qdl<85tAN+3x7toQ--&oeQWLkUIK^`=y{Y z5r)v#dVO*MpX%`7hvG?u*tqk9~^_qyYXa zuyE*lXJce$HXfZlk3J}X4~XB;v46!8NM!!_z&nUNP$qveu#G3PBJrfM&=gZ zFJ2NqCD+o}NrsKkn3&1o;cCYNo6*>)z$70$5j(Rwb(@=KX7{Dn z@6X*+Hok?|K0H}Fw0m16hh_Mr z!U>P~I=M65oc+E2Bcr-WSF$zO`oCtV@t>C2<@51;<@6rBsl$>{V$5y^QroH}wLf3Y zXs!r8XzYyspnPYT(XctSQMT>Z2>qn$^zh~Msl^4^qN78!XO^U&n2)gC9CBGy4+Ph%~MTXVbkLl&8ad)nHuzrZy$fzzayVTZMx+f&9C%0 z@w50$Z4oAViz3vey0P~6Z+|5|Q-kl8ObUkfB1OI;MVwcKrd4y|N(~oYWM=4mtJKUB zJ!{gV({1KIwrmljc;pt6#%qgHNsoiWiLAZ;NcO$7?B|o9O*h5&`Fhpm!q5A&=qJB&xktY1e^qxX z{W#~2^786vN&VrCN|uj<>Xs+FOJo-rYAZfMOS>l+x(y5+E{+!=(aAkHmT+2Q%_g;U(qUKLQVPUV?49PcP zF+CcN?JGi^v=(kXk0RBIq+^y}>$gcIlJBGHnCuZhG|$ylxH5A|y3S&cl)9f_nv1Cw z;iFhM!sXGx6L$`8{8X)y2&IMv0PLeWk0qWoUn? zYMxbo%Z}A4iAK8)HPhCKc`vP(8g;?kT9b!Me$_KyqWg5XXY}55>*11N#TkaBPCU%^ zd$14hev!;of$^^e4e8T#8Wd7mrvfYa*EBB#=w@)b#F`oyD9!&VQZIOV{&sWfDbCi6 zV2?dNcTq?@+{NOWFRNv^vf^VVazK>c-JH$mcG9YAX6WgmL%e%yTC3lvBx##3WN@*F zX_?Hm@>o5W+SS7NSD8DPZ{-z>&uHCM2U{b(2OLyQQ*kN$Yn!I>rMfDS=6RY~Nx>iJ zgrowp@~)@wJt^emjx+zM-<;ZEme)#GEt+2-D3o`BtmPTac)KiX%$%>bxmKlunrvo$ z=PaAlJAp@}{S3QUG{?vjYwxq>@vIoileKWxIozzO{`2aWyWNS2^e^L!&lALcT9Mji zM3je&*WDB;3XP}a4E&PsHg*xF2%KjfZ;ymqk)}0XCv#2=&g&MuU~^a3XpM)fV?0Ul zzH-*7aCpQ8GYI5`lnlM14$(N}IcECda>|o}>27iT3U4owQ}t~V!A$XKOASX(w}&(K z$n2_mYbPKSdvU>4KHi63^if^Tn_)6ar#Cp&ViKxN4wbuxtZOow>P+RRaUGCWaxWWf zEIK@ub0Yjp_u&#KYyP`o?Nb_*C6|QUP{{r6^)_#m+buv@V0`PA<7B7jn~25N*QO&< z%3joaUwJoN|LW_aWnjGIZKNc^u-uUfP)O;4>M!=lE)sn+D5_3tm$}Ydsa2efA`N?7 zPZIg*n$Q>UzM*4fxtQ2O!6@*1$RrF2_C$JviOek$3L}mefX1QxlS!&>GR7Z*DCQ16 zIY=^3U;LS!i)%dSbeXli{i~)Hbn6#}{M}26ih9ef*4Xy~k5fVIU~*b}yfw!oIq$dJ ztq+aomM%(5=jhO!7yo!o$j;hYMo#W~xz{FwGi(sgAl^r0zk+X3Jq_N7A6%4D=hbm< z&rs3L>p{k(6+Fq)-&E67(Mv^L0v=oSh=9vGt@&Q>5`KAHlD4}YAMFP$<-_K(#92V3 zq@iVC)*%4zm!5_r*Ce4tAuPN>L$$SqY#dQt7>*5$jFl}jBri8WP3$aj>Tf9DKTl4+ z?(v@0brI$qt}dVDNxYp7UvM&4cSNxZYm6P_v=GK-!o3fwcaYjJphO;4zGd_z`Z2Oe ze^%O}I#f?m(Zeuc2WQG6EC; ziHvCJh#@IN*FIL*&Tr6_1RWy~|G{2|#)PW>tYTuzLcplgi4^Sv9wD7Bt--ERbqNVy zvL{Cub<4N8IZ9u;l&i&tR#2pbEg-Z%$d-{>sIl=%$w1193eyA1v)r?+isIW+rNJVj zvTUzzsGKj|yT5pe>DTD**0jrU;3d4#(OA#bZ~39s^lEOb=ERe(a~!h$o-gLsnJO=b zG}P7_q=}F`gGS7AsY*<-pX91}j&FE=gjaKf9*DY4CMDddT5|qxfBZ0%3P7nN>6UmY zI8QTE?$(0vJCgkK8SM%y`gN(bacsVF-!`6V6$s_8l~6S7IjCVF>NM73vKn%ti~CI( z2N##-YFpFX8OB}xGd3-ow;AFoA85~2p1n1(m1h_5f;*!ln_t3BZYZ5IeJ1wxykERDGY>hGj&P0WUZ3fmn-q0?qp9y<0~>D7`_w;ZuUCrIQ8EAS@_L-}ghcM5 zoLv3rE@qD8-zo~7vRmD#88r-lUb^RYLZVYgU}O0M>m|sApG`8vXYqJ6L_zY0-Z8pu zu}GBBynuH!sDtQ6psm3MV(W!s%&|zu92|YBBMD8P0CH%1sS7iD%8uyCG*_cj3 z415MC66wTNzc)Nj{d|3^&?AcjzaOO@#vE~?nuhaSN}T7%mERQ)+eS{CZguMrQ@n9L zPG#gwz=as|(aBSFUbl^tzxyA(YK|WLB`)F?8!9{#WYnG)yV*dx>GGQfeVfYbUoJpt zgP%K#REswTgTxGf-ZExqEF2ljdH7T%8{7pt1qf#AI7LjQw zv40&JnwGi*SKUnZW_DX^swa#_eBPnwb#ULlkC#kIUYqvu1)ucFLl=On2ML!VyN6Ta-2yCnHLV6gJw$@Gof!orYpTh42)J!{d!zrHg(aS8gB z{N(TPRnc?%PEOA?jPRCi*dFfT-^ye0{j5f*8GB+mueu021|L52@I!*PFqz4< zX?u{zoI<8Pp8EOV(v5~+t?n(uN_w8NzR}S+6Rj_wfqT+lWOMUNot0a7wXh|VX;H3L z;#+cwUHOXgvM+euXwgV|bL8mJ1XH6pjo8_aiH0Tj?s)mzC=nww$?2uW7F`R>orBO# zBoqShCDl6#bOE8utdz}}39O7kkE8q9hUVf=T&aBHrMW2b#9GQ;|J#7XV2{^kZ~}+A z`RnpGrjb>{-8zw9+{f2h zq&1IDE67QT3JMr~0;q|_=a9H-9_-cSpYs_c9Zt0ZKkA2};%S|NHUFXY0AKN;am57@ z`C%RN(5_r&+F<5$v6EZ3yezY`vAOcj!RX`DG?U@Kc2Y-a8YO*3rG+1Ke^Lnrb6&)y z0kcMk-TcP-*KeRU06)N_h84r&+*~mTGAzb`S-|7~KgQr)q@WM0iIr%$tOHnpV5rWn zt|4Av+t~;Sbu^v5!;ri!+m};DLE+JZ2Ulbi2Cd&UfDDn40RQ27N2SHy631V17=8pz zE$F#kYqK>FPJYYMxmvh~f$ugNniO=~pbjWT`?J78>u`v_!Q(9z+joG8PfE%aE*qEt zkfUdaWPjuapDbwgii(heyn|+8$lMi2A)t)iIN5qwD~0A~Jof`WHT#u6U#0u#jE6&HVtV^l1=@g6#fDQ5Yohwem& zGaRQaU{F6Qrax#0Gr{79J7T{S9CJY9C<7{op!O~71NpO!nabzP5!1~3T*pQS_pmFZ zYSfSuc;hVsn+82W@;)i$A)&|AABSuq$k@dKHOboCm(x+F{amhktqj&oNBo}buWxFc z3-Nr$YV=4xmT$JOzi@zE5})D7Yaia6>+T51U}C{FQ|V|ZzT5(ss<>zM8Xw=+)jp*D zq0haNs7E#jLtqkBePGgo31~3jI}572ngmInO=O9~=Q)2fU@JwMKvc`9yW`^5oZ2w< zAAf-J18+u0TsbXO10xysP*UpTn}w@q++VXg!;l#9<@M9%=_NDjNIE-@zh}Q(L z{T8HkOjiQt_TDz}`pMX{H|x-PAY&ntvy67EDB^_>z6?)S9pl(O&n@vhf6Q7Pa}&t`|B_B3aKy6F27%^M;-uqFxk^z>bjrD~xWHitFK?tF zT0=PQ=B-;0yA*>dIs_NFyHngH#(pHzfS;#;)a&iCKx5SdUrbC3?jdQEFP22 z2H}mQoCY?(6d5!dasX3cpmdP?;X%^>c`n7Z*A(Ba!Tkpy0$JV2$OsU0&{j4u2hPdH z#-QwpAV>fO*j8XMZ<=yGxY(L+w9~*P^kPGi^{Omjmx)v{XUuTASMzh$`S-(G3Q`Cg zF<_@hjfBPdl-vV?V!1Q<>hEn(YQ+hUO{#yKcN%76)Z6Fh-|s&KP`RC&yGg@ zTV6t{6;$~Bsh)zLCpd9A==E7%nDRXbdjoBPVbF7S`z9px!de{=WhU5j5t1MDNpgl8`nHFW4m*OF6G81tYA`bVZXFJAM}v;pov zkn3Sr6D%o69Lk_shT;J@JMLqn`#-)4I|g|OLg=K2ei|fkOet zJdBn95kUSCN}5O^_ha$FrvUr8*aIy!kgb904Z2c*Fk^xA3|kgWmEXV*Nk|s=w++^R z_;8n68Q!2|vokX&U0(G-wz%k8dMVN1U2GkOd-mj;r>NpAzKOTxy2nazpcXOquFqToyxkFqzr!HgQ_2OrivNucp`LiVmv&}ILP3-5Kb3A z0&9@j#l`g>L8r-B;7)>o$p6`zcp-=280%+YVQ@%7-12<-oe&yUm9z2PPQ}s=IS2tWNwyE7)iCLcdAr3q%`)yz&c%zFUcxMa{}wd(A$>+NWRmtwNpNd zS|TpQ`j*JJYn%R`w$E7K3H0LH7$ym^Koz4V2hFqa@b+(Yz`aXK+^SeaNSui|lm|u4 zj9=crIXz>U(in4DVw?A$2V=*#JG;74AyGj!`*86#503)PkVM`i z6z5F*w(=qDZhs2jgbyuJP5Y(Tlbm1w)ExR2OdZVYi`wwAww?iv5%zN>_G5-OZ>pVX zitf)`<-$}0WE06dc_6H{$LmBPUbyIJR!iTSrM%QkK7$eGo40SH#oYwrn&Q9<-O21e@Z-nPP#LO2 zLIhu1@b?Z9vrtJu_A^2>$QQn9QN(;B_FG>h&eKwt%gSklf*k0_OAbtC3MhMbii?YY z=&@!>kW!#wfYDQZ?^#Jw51c;E%MjCK?YW<1oF&=6)wu@LHYCeS{V~VGYmLL3#Uj-*RY@WQaj7KDejpZE*8V*c_=J@3(1=RgkmV6;ZcV@aNiO1O{Xbsg2G43 zZ}xSxRKmmaYCWf#safPHfq7|J$u56pMI$1|aKveYqJw7OG{EHa(pg9eKC=M(HVl>KcH+zmYvmlsXuF=qS-AXe3N@IxkU;oP7^TuD@ z%@3xT63X0e>LQCWtFK~myXf-zQ`W$#STO?b;^GHei|;a3h{=|DOX7hgw}g6Lw_ zo~{N-nY0^@8YCas{a~CNxOLq zFA~e1J$s}+gO5tteOmjSzLAlNR?|Nwv-4GKeFQR`VFKvQ0&BZQBP~einUQuK=DkJX ze?Ojh;7eVjK|gPNq@~doR)l@HY-Os$t^%7AUCpJE=`sQl#ZTBrDIua^2{v6Rt`oRA zXxs~lh@eojgSFV!yWXpY#N*_4i{5X>j9Juq{>+{$EGPcsN1sg2o>k6h$F;*u#Ym#u z`k%zqUMP`c961jt!=N<8d2P60zG)>`9$>nh{g;D+?-LLdge}sK2}KN$@zT)bAuY#| z#G_4IFYjH32BW*F{M*pW#>r}IVggs2_O7ngjO?tNl#1(D^ z&z9SK$OL^V(QL)`kT1j5hH?-nE7zFUA)CK+zA! zjd)zk15Muu7B~q*TgM9|7|3ay#=q|RS77ytAeT+NOaYh5^b&4*5nJdMkB75CKp!PTxkFaqf!WWOq1?=xF2iLmGaOu5@jV^w?M%_Gg^#| z?Nzr6RtE;iN2U?Q-hdZ)li{Az((Y|JN}JW(c7`g&4&&BShA&D>Ju;opTwvrkQ$@H! zz1lc357vnKq}b8WfT(}>eB(HR{#Z}S@{dQsq^l+Sq&$Bg<~c5K?ETf0;?E`&zPxa? z!Ox$~>C)xHy#JLG!uO3Ykqs)V_73qTTah6P!WzV8A)SQXfaGoBLaEH#o=t37t&iX$ zpKgUe#7kN?<9}BUMM;J#*Zn1UeQES^;E`~x(KyDd$uz_(z}&BT10r?uL-V6!H&r;Hg^+t@Mx*p1G2w z3}_arvgn+D-_vaP_wPfPbTKks<>}dI$h(not0d-BX_(gg!JgXu_S1HQ7`}+ftmF0~ zQUTXb((d*>5C&%(Y?*bi5O~yyRd&ANo%U2?uh&Cn-dmsaOq`a!AOhGJm=F1;Sqv}V*sp#z9hRfa;Y)n+2(_-8aB^D!%w_@BL243M% zPCd~*!4b80nAu$cYpobON`I&|+qt=QQ3i27)_>@F5S)&NiJ-2mL{W@~VT|Kol_eG*y5 zg7I))K71HNb^rzsXd@W)dK&-++H`cMG=EJ@T)iwvTq{BrQ$1u0T$2j{(U?q<{s(I&)wGp}s)0K-PqpHySV^9SFy#G!EZ&O2#7n9$Mctu2thyP!@y@KxyO(R$_t+14MKJtP8 zUmV9a#h5Gn{2x_>Qs$kjsN)`N9>hD0QkDCC%PY1@1)UC<# zj3O^6nI*o1D20;ye-V#JPxt*S#_;TcU=qjX4ai!he_{{@lwj4?$G~nvLF5VRLg}lf zregrY(DCGq`10S~^L{foFppFc=hkIuX|=ebwMkepta!Y z0r?5!Hpq~{qWXOO7;$X~JOt)BK93>YV#sSNGy?^+nrn7xNy1?qf@f7}!Wib_(H0b; zFt}bruMPtF>VK@vmk6MvZUV3$r0B+V!t~d%fq@EZ@o@A|!8vW)+_QUkx_j|{yo>ii zxqfP}shAiT2=`|=)~O)a0(iiscSQsd)1B;?U+(v60v*)$DheZXadcx<(p1%H00cjk zy_xw>$aIaDcIw;r+?!V+?S67v-*9S7c@978eO))AH+D2nUjqaP3kYs)m>t zCn2zczkmN?w#ouJRN*OQTw9?I(Jplj-|zxw3MKHS^uL6_>Yi^2Kjh1Bg97yky0Squ z_b{xdL9qW*O${RchT;Sq+GduQ@zz!_5E@zn;j*Wr!wEg6QrE>l2&3<`vmDg0(-vL; z2SBF)pd|jowNye(Yz>s?v9U2|w}7W$#TsR<6PhWKZ2vJ<6YNizPu7C$ji9~emjVBv zUPxG>_P-^da3MZnAi~t}u=t5R zT}f+`zdvT)i1vp%XvnB-VAx!IyrZ<>iJCd&6&zQ04#7`10x9EDS!?M27A;oX7$67A1m*WRee(v?2kPv9SB&A2P&~k zN~(ZF(qoV`{2iVEq&hn{2QVxsAmE74r>ZLO1g9D_2o+le#ed)+42&{g%W_9R5T?t3%vCv@5L$)Lr<_=<`@fJ55(Vr^y$OA6Ga^1ETDo?c^r$<|qCx z;M|-(!!GV|XzbbH-r^VHUT4_Ye0o2kY>=o7{ROQjdp`q zHWuFQ+2}0E298KU^e?=vNf#UanLRF&9b61_cf zNCSyJ6W&+l^auevknrrl2lY~GG*U@ZNxW`1UiZ~C4!_M2 z^I(N?lg+!!eQqI>foQft29d=iO16Ei^J)ZO{VwjE zrRx(Jwq6m3I~Hjwx9ciJokW~Cq4`OvSYk1Nayo)6+ zMscz)?Pt+d8)$p)M36d=-EYRyk4!)io{ACmB~v?RZ(1MEK_#6zIy~JJ=I=E1G%l{m z(czl^ztt`G2%Ry;(5CTS|7!X+WecKF*1q%K24VLp6MX9{Q<|4ijz`&Wn7IgUR)3#6 ztRwPsZ^bm*zh~^vMZ)!BV5LG#~(&f>I6mArqM zN&e*13|)Rj&myz>mQRDMm*ir_qH4Rn5B|^lRSw?iDkxQ3?#r$-Ssh9bJ+o`lZFzli z`P3mQiJE>%XC*8rxvNC0>9s_~1Xi=YEx1hi(e+PdlVlg`cvJW>-)Xn+4?QOxz~H*N z8@5QzI9V=cs-Fn2^D3QlI$wJDfH)dO$SF|CHNTX!|3Vm>>6O(FT9Z;88l9SIv~(e) zBDH91S6&tpE_v{W zpj~W#C8He)KN$OPHdK9WjT&Mhu?_al2)0m`fW-~AHPj1=XU)6i6S?#(Q~fc5F_-p)pR#Mk=G- zEWaDdQ5R=toZ7%xprAwnouP3$RECC;@$Zi+@=W!Kkr6ru23aTjjWw6xORTg(ZkXko zBao@?246{7L;-PXy_woRj=mxi6`1zLio2;d)*%Z(2B(zK4$4r178u+w?uEDbg)OM>tDC(Em|Fy+|~I(<3Ad3`E+G7)nRLS@zNy`At8J(kQeGEzK+?W zSHnL#gtWn30>RIh8ptJbdEM2n7(_=X$kN;&pTzBZ{TghpwsY`6cY(`}RQybH`~?`E zpscW`15XVq9v^C`$#7Zm$y?`BE6@4+ju z%XoQJ;MG)R7^7ffZhkd8@XHWFr25~Tzh<4GXG1onoW_Td6Udox|FKTNl1GmY@X~J> zi=ioOap#V`NG}d?G+Kc&Ad+tMxlOkOhj&~WN&os)HD6P{5VL%ny1Ix90&E>080SM) zBvzC#uxw;|3n6%qQ>QHOweSW=ld*E*(-~Qka$P+%?U1Sm(Vj|Q2~8mEw2`KIVORvj z^u*A?AfV6ZJuu|@^N=kg-|dPa+d|9!7PdT{nm!M&8=EJ@!<$CzinK+}qw|VI2DyzY z7lyWv|M($w&Lu2?Ls7A*ZURLEg2{Uf0I9lC3DY}>bO;En+$+u!DTyp(d(dgEC!!-W z#0C)PFddzSrX~Y3vtl853dz80hKJKtxxmj46vkw}vG<0Mt5{m{qp5#PPOh)5+DQcj2g_Hjxl5G4dl%U>0wdlR;%)^$ zPM=5KWq^sbZ7`YluwbaOpUtIT;bI< zHU7T7?WU&*9PLtKS{wHOKL{Bx#E+ijf=C2SRnNbZf(04gUKkHF=O7{Tk{cddYR1n| z6ce7{o!0^h|^$HrOYl zv=H&Z=K>uvT%!=`eGClUAWLA;gPNi0)()^=3f(@OSX>Hza8JZwO&mRnCu!%MH(xx$ zknJC{&f$rQJ7B4SMGoaW)Z?(ug{}`@ANo6-eD>pCYX_u6N_G2@1VRA_D?$7L6D;7O z0D1)Y2BgB$u-UisZwCeCZb;qT!bPcWyo^!@_qx61oDTo__Cq}iX?0_g41Ab zeu6g0-1!zf)1pxlU{D3PYS^XqsUxu)|A(=wzibCvwPV?x`>j(H48bA$r&S#2OkawD#m~g{V1~mv# z3FHc?&+to4QZ_}GI!QSVZFgw@;+i64lNQR+omX(k1A!q)xpv5Q?0qLz7Hl2CF2RMs zhQk7c(y!SLonx4f5-E->TmpA&y(<+DhxeBw*{kiZN_z)i<6uSpkMIr*gq}yAq?aS& z3*xqPc`)Sh==xk=O|Ps2#RU5fxC3SuhlPb<5)`%rfU{1-HVmc3zO74XLiQC&gV|`1 z?IObOmm0l5K_h+edrs#|$@@TT&=-45{R3vZ6BDAwpC99Waf|_es`Jmz)0~9i4WVP$-HePXmKhuS`s@tl}d2TpNiwg>#-Y3)d!fmQ30Lux1N?rXK7Th-` z4p!Fti}CvHhiTQcwEn_m3~UZm2C(RmW4D{By+}{tckiAQXaX2ylbV`}i;a{JPQbYE z$O;i7mY&0&$G}7ZK@g6f;^N}Cu%8WcfX(kzbwl8QvoL--$zfDT`27HWA4h^UHfA#o zoLN&zDLy3y!pZ#ry)7Ur#eW9}rU_1tA*d(Y|VDv~?H&Yz5&e9y}9UDWp)Zt>DTjNfFsYaor8^C}t_ zcW#lv2-J}ax!c2XatM2Spo2XSCIMKJ%rxM+fSsvIa_H_Ifzd1~hEJGlgCF|h%_Y+Y#5G7%;kF5< zL!8AZO<>2m6C>HQv=D5e8UEd0ehvloXe99*k_(IdQ^JXDW1wOp7^!GzOplIMunP(B z@Vvt~3&>s#3r zAq4YUr0sW;tWdpB8e~SAbMZ3CW{*w2?Q1V)Ki7mX zd>F&RU~Ue-K`dD`rW1aW6@&4JhyauqtiHF`PvTd3ot@WlbuiZwtPbn`jqTJ&MMS#m z>rV;_MvNZ0mzAA8jYA9RGhFIAN0$aks}6=B^M|({(#0~D`D6_6>+g>ny?Ac|=L&kg zsFIEcU%HB(ZHeQlg}A*KVVZ>Dp*X2P@`BOk5s^m&xC^K_ngQVIm3!)FYX0eU>X)Qr z$U&P|K1mr(`ljf6B<@O>p^Rx;C>}6G5d^PyR$UVAFNJ=FVrnT|thP(S3=#I1;piYf zeth1ZV~YdMP;la=%l=YHKF0qmXlfQ?eB^zYqcyJLM)nQy$kRBh8g?;xF9CM-XlTRS>NMn@57uwlZU zJzH|IBKp^`+(b)PL+Zya1{!HJnJ`ZSJtcSKpal61C<3+Yoe~K5Ae7-u|8$9| zD^iXfl5S0N%BB9#uH;L^uA z4i`1jJAjt$?n1Kltn_q6Q2%=X-Gf-EK@5-$YHtaU0lflLk?X3(ZE zytC5`%ZK14#P$EE3Ie@xfTGd*s+^pd+tM8@kH7@%RTxoy&%|RN@Mk7T& zy1-@r7L7DM93mvR5rvr73ioSlAYGFK6iDpRr^0JtqkuW9_uT|t9>_R8N<0Ve0%*#h zQJ^4ZvD%>mgdZ;sSx_9-;keRyqRB7^Pem&c>i>#CYroSZG$xfN`1#u#8iL)f;z$RQ zgdPSx1*uZn_8RO^aNm&dz?B$W&L?4EWA-9_-Izqd%K8@G^VuF}?^&gmm-kmzZu=Y8 z+}Y_2qWZ?h21+zE%-BV`KVy*)?2|3h=VfHb!ey&8V9<@P^kxW~kQm1-WP?oMe#ea+ zm(T_TDueBopO315wZ*1lb1yaZwd>ad5^mqVor(+|#s?^^0u$g3gDM*=frH=bD13kX z?oZ9k1ZR)IJq{HC3aCU5#2NGuD#En&j|fCFF*9T0?(|gD@yi4M%LSNHh`)A-i76Ws zNBAXgR9`(rH3CPQ@8V}*LEgzsM$djnAiByBU>Y|Mk2T!mkQ!G+V{{BwGm>zh%%z2e z$1<;QZSOtVorQ1Pw0RYi%iyYWNGWvtHB8<{Aj_HE;0T2O%L#Gu-u`}^Sr}<~8x5+? zB{=r>{knU`Wb@jsTgho@V`x?HjJqg$?p!}OD@cB^5YcCTFS~PN4+~2?PJPr5X!OC` z6Uc$7nVF$Hda#{$w)$Q?iaN{m_HF%)le8K6`N%+{J5^abkrmLM);)Rjs4aLoXd5B# zjEtmT`$)&npAUcsq?|#lJhFS3kPXNRndyFp8`Q`hFj5XmuLo{Fkz^um*QYtz1ZgB; z|K9XN8&JO3Uj(pDUdxBR6axh5aL#h6>{G=Egsz+ z`7=5ggN{K}00baqf}c6I$;k1oFt^5JC6^ASQ;+d1eD#fFeUPEL&E@hp*d@zL#Wr0G@>yI5aHB~-0kcA@Tv`m;i3}aAVV({T&AZ9~i zA}BbMOfvj-Z%^Fa76=Br?&2is0J_w-SWzkMT| zxC0ZA1u;O1fjIksYGuc@7arR{WJ5wRN9@v**GV*D=g-65A1P|KcG10rQ9KZJ^h^X( zG!=z4`GEeHl#~FMGFn~}c3t35XC^rej%!uQ14$)590l6i z?-5+e%3?9@nEnnm@o91Ya26mzz`koX;rWgaDhPQupfuRx-}!=?6p8DDX&z!Y8Ml1J zRj^(#=}J;*0gMWG-4^8J;KY(rT7X>{e4#F;Fs>r61+(9G*+*DJ??x4japS$;zE%Idb1ykFQ(jtn z2&w*eMnDxnjVvrq6=>?{GiE&4Kjy8LArt=&mpC9&I0Hbl!R@Pw&dbjq zbZ>Zr!GF!5=g-W*f4>XtoxlVDvv3_^)E=Ciq>M0_!>2wFqcCDE1Ox<7WK|)`Cc6$Z z{S~|bhzHItF5nviqt-@!9W5q+-+%|PvaxSS@Uf>_yhGtZ|xlnj8&Gz|;MI{AR?w+QG5~0PjF45B?2FLi(+sFa_!n zM<6<9?$A4P1RfT#4`>qIbtx7pEJ`3Kz4kL*9MCTJBtYktosW=jW3)zK0uU-FWMC}U zxkOk?F)-|VW=r-`=r1|0uCOpdPPA+iV#_|J%LC9p5OD5=3-_hs(F(a=Ir!q77a$%B zWP8AhK}Es0#FQ2*bMv0JCVNy#-eU?&CI*k-jTjixf%?mz(ZkIXFJ7DXGO8%V)}=jo za23@QvY58pdFM7(DqC9iS_KCN;&42#lvh-A1FQ)YfXF)$+>Uc+duu{ofCbdTxt;D? z4U&d(Y;2sRG}1s%B2HJl9@OCSznO41O@xh#2=36r_a-C@l}R zHv(9=cmMv4lizTfojQ4vlp-FyAdE(*l5E*d=U)i`k1&r-~QI~#QeHV{B* zX{4b$zr-Fk8>ElJo0DdD0Wp&rO%e96U2tJCP^m+D^b>WUvp?lP6iy5DD$w(Sf4QGj zyuOM)V7X=-zMnoB!|cml;=HzX5HE(-U`v5U=wZ_sgs=pFp18{qf|%%oBJ%0TnH>!N zm8ezq&qkp~hwx97=#KF!08h{cKyqq{iPF8%v=q!#{ump3Pf;DHEXb6i;OyhXTL~IC zLmRaC<#ajjTxDHdpxZqPu5iqs4)9RMb?fZv+8d$djlc#n&uMP%DRWUDKR@Kf346~;iE*;=`_ZL8*s#igb0&Q4+^H;B>**Z2^J-&{c6fbnX}3k}|a zD9P91^acktigi63M+gWotpnfDU~?3#?&YN=M1FAKskuK6+{GjboFsROGBX>Rn|XwV zqp-T5?*Ds-f!-3kkAjjC6ACM4sngw_;owjCX zTv2jh{qpC8qQt-lLPJ9rGkHNucXSj8OhD$0&tDbv2B86wci(fRYcvNAfJ~X&^&6+b zbxqA5J+p41HbRF`+cjf?&OyU zQ1>y5X<+jZ2x(!Mqd$kqO1TUgSRMho^qV1iGY@_A%q~)mgonLBae2^#iO$l@g%#csDSii zNEc-RQaAHkw`l3yqyJ!ytFV6AavM$G@Aqqf z-(tu*z@S9VP(RpZ^h;uUd-elHZ**?$p{A2g@g&{OE<c;dV`F+hl zD5P7^=)=SS?EAmiXdHnUStZWF5df5F1bjU78`uAz?#?x?#jD4+;25D=PLB#Vkt7k$rW>liGnU<8^|83si z`}zIwetOr3%Ok*+#JVoo+nP&!-!7L?(XizMcXmW<$)XK&Fhu)Q9LI+{4!Y; zVlOs&``urOGMgC@Vq>#_d%|$cu%~7*{s94XRX=^*%CMKIQ*TfJ5U?tN@-7Sj(<=l9 zf$@^VMvORVd5y9ma@S^)Vg|Axgs|OX7s(wY-fepIit$Ex8Xlp*jx8+*^86jg06y&L z^>MAvy7fm=Q|Dy5xB7RI^^#iOoMq@hM4~PC&F>0} zj|b8ui@+aQTPqmldVN9Fqet!@9=SJeq~G%IqD&dQ9$SF_wtn6mw)ApP60uND&bWw) zDVS}RytA+;@%N$Rd|5}-K51Vj^H9Z;Lx2ZQu&H=CN9K~aGE{Bpg8m}T1jW9jK< z7Buk+#SRAWX{f8S%XH>-%rjVKYIvroC<>=fzC%g|H;BuhIl^!zwvn)Ath@8zp+iE|1lc%l z+YzI%{rg_ExrA@jQLJXxv9VsrJ=``^lVYttsZ@z~Ul5GetLq-2@EqRJ*r}4(5%#ZB z-Ug1!yyK+*q>uY$>MCtHTtT-mIihc0s4nKC?%{>_>!iZM&uDUCz@jgBp7~d4=?sui zIj1Q3?hBgx3Z43g3{jIMvi4-})aHm~Y-N-giop-?kOxdA#n=8~ev||ko|<&6w5)8T zQ9N-i^KppaF_*tkvf)#(B{L@{O4aHY89=_dyA05Pk)#FNKAb&rq+g6q523?7Frr*a zuJYj5UuQ@HF}`E^y&|(z>SKVWcfEgt^Nw@1i;TY)R_|=$hy*HKh#UA8NT zHG*K$dUc$+siZhjoo!lI9GMEt0gt#h#`?VNApNQ@bAE6>Z!9d5?RXn(vgy(lx!$UR zmv|h4NCq2OwZB#`DPk5KSZ@`uZJsI6HziNgT1v%bKb|_ZTj))tVxSBu7z@2JFmNBT zS^AQqg&%5f>Ly#SSseEm^BNqy_xb+w+1d18C1l6A>+0y#J#Xj4fheQ+M$3VxHZ=6k z5U4z1=x$TfMF@5`H?v3Ex;i#79a-(k%EyiG$$*Nlzk7hjpBb~i;~kYsRdD;AnI1L( z7bkMm^tAMMCnqK4Vl1#*ILD_?UsJ@<($f9D@f+d+BPUFr1qKY&Lb&H~!$-eQQM0B) zU||<&4lsbW99QGEV1Y1SP+N}b1q#2uY&F9`m;^o8&~QeeR}5p?H@%YGxeyCJ-2SMv zKFk&z*2ZKl*dDMfc81q6xEqfHh)rasEHA>^V5OQj4428mH))Ghw^12gyS8oCEY0{V zh<`Tctt%X5x{(RkfRcc^k$-huM*1rH1fs<#^TN=$VarldfH2tzd-u8km*H!f{j(cO zfltOpph38jOBl!7V9|Uc%cUcxmJ|U6KdPxYmXzeTc5TAbJ(%d;I3Z=oG_ILw54Dc^ z_K!V{R*CjGaQ%b=D9+8SSJ&`FICsT?8P+wR(L9ZPuJDWEj4;`(G&DNthaXn?`Z{E~ z<8+Y!IR$yfC|EYMHs__&kVG->=({;@DTe{9v8`>X2k^oqf%_C3u&N29f2o>I;)JvRuBv)QMFYlb(W3tGS*{jO zo9?hDheX~x=E__|1kZ*z8X9RFs zlA4nT$rqBMkgGX44{zQi0G9~Ihs%Kn zbud+i#|(|PJuNFl#;JhBQgid<9xaUb>R^a*$j-G zIg~{Gq$T(|v;DpeaS4fK|AC zz|73hQ2m>(9ZLnO^43@m$q}^H-6O~XD=-_mSzGByr<~U*`c@(;j>|(R$_zZFGK*!( zkcgo%A|3&wkn}) zX8$1OL=|75$b+705NNJY@v=lh?ugBs@7%hze)=dYs|Po4ir3|J_NolJ3_pO!gBxSU zP7cL?U|oO@VVgJ4mi&0>(i2)Az?B3}sDAu-0>TYfi$12Qy(P;`)kV8p@M$||000lS zFE58D`ih(a9uBNIz%+oY1WfGq%H$%(Jj$iY#Hh~8CdOW4`nfDvV6;7t`V+ndtaitz zPviw{1O93Vw=Xa)yO5FLuxL>`ZQWT2?%L@yXMn1}-spm47PUuU-9DgG(s8*PmGM$9 zI_Z3FF1SE?gOT~5_$>NKwY9fHIIVGT5Xq%v2OwyJrmXumAOLf56IHK7JbuE2CAt1R zD*bxI!JM$S5@ww{eY$vT0i&ZoV_%6w7cE`d^WEXrT|o7m3}SG1qh*(a43h7<&Y9zP zsTu~JBeb(9E+?j*0>96h+&-$n=zYhL^>1JKhMGYN((v0qbL7xV5Ry< zgjR@jfm`6=!9>rvit+=TJyCSgYb*)i7{du|x4wNrZ+d=HK6)e_H|~JcnOnevbR_LT z#r^xtP$kyb87lQBu`{JnGpnTxnpiv$mJ(|y5FcJ3#kgNm114TGl(}w&kH(Z~T6~Tb zWH;d_Ndk;7OZ2|ARS61KWklvLEoYmM)nIX9&NC;N&y9-eM&ZWUrpAvjU+3_E76gg` zV3|m8WfDQAQd%mXbrMmvR9pRUwUh}P#0g{_&0TBar#4l0THItIaCuW?M<96oF&$ovZkblZzFrfqiIl$0Ltt? zc<^Vm&LpE^*$hWV$ZSB$xQZU4=Z$>qx^-wIGM+SI4CsN9>3L@6?)qSNMgtX3kI8Bv z2V+c`qRj@!0d;%%(j{~I{-Vy)VDg}4SR<0nJJ~*(vC;o*3$$HGZ_p4h+SM?*9%RWT2alm2y7ePt!Y~js$)S3%d|2cr&He}p5;IgiH`)~VN6D+a> zANf51u>i_H6l7gL+|kj~J4WxQ-?Yqn->k-qTREi??V zx3lZI7mE;q;7L*49BQcJREai@M#v^^KYA2KddC+4+_2rz5l)N_N<-tC zlJpA@N`%X3Z*U1f0aVbDGu}Rm^Cr;<4Gc7bM_;%wkIs=CA)L7|nR`%CLDw|gI^T_toKD{}8q0Zj zB(Y;ibz);R3Ma;AvBBNk+)h1d#Q87F^=ByX-_aVNKj3xg4^}e8f&rKticCb>mQ0K& zBqsAG2qUPZW!hrEFchgoS%A7#|3UZA*f?_N&h_n5pNuvjb;XyUwSTi=RhiNa9YZndQZIFLuDNF(a%#?xOO1A(UV z{P{6ZYG!69K$dtDX#dVStR{DqsNdy>vCR8A4p5AAvN~jP)mi$G*4Jm@6Myo=_F${l z1P2?4nSi5y#Sz>eWSEOtbw9N>)wB7*~G?qz5 z9ljQL*AVAGtF8RM7#AFxjbDOu145Teafw|^^h9DU%v5yFMTNpaGK{&bOF=2EQeBrT zeATXO12i-+NP-#g7eGtetH{}dSK|Aw;>-e+sMOFlLDOG7;cs~>6{H@lt<_Xf&)7iu z{8P~Ubz#&-GI0Fc#fymqu%@gjA&{a;&8ZTJ$x!WshY#<}3PO6x3C+)+5)o;UOi6$D zMfbC_sbSL%o-+<11?kZVrkn1NBxgvFJ6^fZegQqNcbk%7%fAfUzDW$)Dr9hqopjbHD0lP- zCpX}UDgY>nWD)B$u+tAR^^Z2*J*L6W&@Xwbs zGlv`zkFFqoZxuAR!;_pj7adCsMPf10qsVw)cJ>seYe3KN3J|OkSr{$Y2;{62m>zbKG8eiL5~)7NnRM9q=EV z>CWlo0Heo^>n%$pS+O&t1eFmgGKMu&2M0FV2|XF2MH`ukH( zkzfU)X(~%3G8kxVT)PyRiB|xY1X>EZm*QhzVZ1K!l=p^x%zGrSEmSe(b{RKkX|DgR z?{)gLCJ>$~IDphx$;@O7%TcsXC1LwiQ}&Czb9CzE%Fs7Nln06=$7i_OfedpQtHv~2~;w|H^&*|Vd> zGN4w881tsnK4~9if!@LJf_r8XK!2=XUpR}!@FAM}#H8QkyWrYpbGN*?gQfazy$guK z@krtq%%Vyk1ILk9HTCz=y^kQIIz;H0R;27enMB_c-}HrKd)|L`zpriHCAajvACtLRJH3r1f|jJ1z62nW*Q158JygwEBGiAs(u__b+e5<2Za^ zr+{JDO8bm6oH#Ht>WywjH3{|Y7h=;=Q(r&3@jJC6K^Z^8;d572`u_R@psMr^qj-TFZRfMg?NpESC7#pX6yB#~WuVr6W z5PM2G8>%0~&a}PYq;il%S-xH@qwUnK9mO*E?#GSc&2z}VM#D%x2!n|xiBhnAD=Owk zz67G}=s;ObV?L|l-L_Z%!(#Iv zg^Qy^yc$p=K7PXF$+ySal#mT+;w5gY_?p!xF z(pQBdjLJ60t7b`vT^Mh6crNl=kaS@>J$ZvfOgj+12caEWRjTNqV8~9mjfi9fxf14r z303p~UV-Xy?b@IDaxyvF4xPpxroT0<->V66J`A*h?E7u4P9 z>ElCQ*+qURRBBkxMrxjY`ZRrLsl;EnXi?7Dv%v3TMvsQdfdBqXs>Jc2Fn~rq^y_%b zb|^|C<)?D%Iaaf>ay(P)K6QTR{{X*-&XGKmrk|{F1x-g0>vCVBJ@$e9v5Y*Q=o$A? zbJAE%;##VaeH~5tw;>_tp#zAoDCB@kCOk*F4C%NlkC=*BZ9YZ2CBA$u6fu0tJCwc3 zlwtU791L?U!g}XEuB_D2*0#2>`4`R0CQdBdwHq{wDn!y%NAMzC0x=_k6gU*2LU5=M z-P+l$|4ohH4~xS-=F)b&`zwK=;LI?GI&U?lX(YJ0g_YIQXV3O$k@Yu{t#NI+!-Owa zQGpSqzyiO;tA{7wWwDeQm(^NNsGBXGRQqy6c({<}BPODXhP(~{<1~WbhK9I=_x=0! zO}F+_Z~vf$H{_kT0@XvzYdwFx5rp*`?R6elB?$Var3J)rj-=7@;fKllIH-I62KmmKMRWAdIoce!vTgXL~rH(q%JUeEs=!4K&WU;-1{ z>6*d7C8N)4pfkuO*{w^wy*ts18R-rO;Z94_5UI^J>F7}>63GJacOfB>b)`MBV#x_b z2oHr+@SnV~c+r4?12?+;+JnDn)n2yv@)xt1e>DGOo&U>>l9&BoB&Ppw-zKSB>-h)0 V8P^TeM+$d%j??^^*)x3Q{{_#ketG}^ literal 51521 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�Em#z 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%0A8Da-@9du~(`j%a9ihT^*0@PQ))<|FDvXbdD;Ltc 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 YpR1}$6PLER3)kLZj`QqO(&gL!1sa|Rm;e9( diff --git a/docs/src/figures/inner_layer/make_convergence_Sinvariance.jl b/docs/src/figures/inner_layer/make_convergence_Sinvariance.jl index ee680d53a..ec8b1a4f1 100644 --- a/docs/src/figures/inner_layer/make_convergence_Sinvariance.jl +++ b/docs/src/figures/inner_layer/make_convergence_Sinvariance.jl @@ -21,8 +21,8 @@ Q = 500.0im conv = IL.delta_convergence(p, Q; verbose=false) names = [r.name for r in conv.table] -d1 = [max(r.d1, 1e-16) for r in conv.table] # relative change of Δ_odd -d2 = [max(r.d2, 1e-16) for r in conv.table] # relative change of Δ_even +d1 = [max(r.d1, 1e-16) for r in conv.table] # relative change of Δ₊ (interchange) +d2 = [max(r.d2, 1e-16) for r in conv.table] # relative change of Δ₋ (tearing) n = length(names) plt = plot(; size=(820, 540), legend=:topright, yscale=:log10, @@ -31,14 +31,14 @@ plt = plot(; size=(820, 540), legend=:topright, yscale=:log10, title=@sprintf("Convergence & contour-invariance of Δ, Q = %gi (q=4)", imag(Q)), left_margin=10Plots.mm, bottom_margin=14Plots.mm) -scatter!(plt, 1:n, d1; marker=:circle, ms=7, color=1, label="δΔ_odd") -scatter!(plt, 1:n, d2; marker=:diamond, ms=7, color=2, label="δΔ_even") +scatter!(plt, 1:n, d1; marker=:circle, ms=7, color=1, label="δΔ₊ (interchange)") +scatter!(plt, 1:n, d2; marker=:diamond, ms=7, color=2, label="δΔ₋ (tearing)") # Worst-case spread — the reported error bar on each parity. hline!(plt, [conv.spread[1]]; color=1, ls=:dash, lw=1.5, - label=@sprintf("worst-case Δ_odd %.1e", conv.spread[1])) + label=@sprintf("worst-case Δ₊ %.1e", conv.spread[1])) hline!(plt, [conv.spread[2]]; color=2, ls=:dash, lw=1.5, - label=@sprintf("worst-case Δ_even %.1e", conv.spread[2])) + label=@sprintf("worst-case Δ₋ %.1e", conv.spread[2])) save_doc_figure(plt, "inner_layer", "convergence_Sinvariance"; script=basename(@__FILE__), diff --git a/docs/src/figures/manifest.toml b/docs/src/figures/manifest.toml index af3425323..a8ee3c49d 100644 --- a/docs/src/figures/manifest.toml +++ b/docs/src/figures/manifest.toml @@ -25,8 +25,8 @@ depends = ["src/InnerLayer/GGJ/Ray.jl", "src/InnerLayer/GGJ/Galerkin.jl", "src/I script = "make_backend_regime_map.jl" [inner_layer.convergence_Sinvariance] -commit = "20887ed8c-dirty" -date = "2026-10-16" +commit = "5b51d871f-dirty" +date = "2026-10-19" depends = ["src/InnerLayer/GGJ/Ray.jl"] script = "make_convergence_Sinvariance.jl" diff --git a/docs/src/inner_layer.md b/docs/src/inner_layer.md index 17e50e8ca..20dc7fde5 100644 --- a/docs/src/inner_layer.md +++ b/docs/src/inner_layer.md @@ -84,10 +84,15 @@ r_\pm = \tfrac32 \pm \sqrt{-D_I}, \qquad p_1 \equiv \sqrt{-D_I} The matching datum ``\Delta`` is the amplitude of the large solution ``x^{r_+}`` when the small solution ``x^{r_-}`` is normalized to unity (i.e. the ratio of large to small coefficient), in the physical (outer-matching) -normalization. Imposing the two parities at ``x=0`` (odd: -``\Psi'(0)=\Xi(0)=\Upsilon(0)=0``; even: ``\Psi(0)=\Xi'(0)=\Upsilon'(0)=0``) -gives the pair ``(\Delta_\mathrm{odd}, \Delta_\mathrm{even})`` of GWP2016 -Eqs. (34)–(35). +normalization. Imposing the two parities at ``x=0`` gives the pair +``(\Delta_+, \Delta_-)`` of GWP2016 Eqs. (34)–(35). Parity is that of the +displacement ``\Xi`` (GWP2016 Eq. 34; Pletzer, Bondeson & Dewar, J. Comput. Phys. **115**, 530 (1994), Eqs. 32–33): +``\Delta_+`` is even, ``\Psi(0)=\Xi'(0)=\Upsilon'(0)=0``, the **interchange** +channel; ``\Delta_-`` is odd, ``\Psi'(0)=\Xi(0)=\Upsilon(0)=0``, the **tearing** +channel, whose flux ``\Psi`` is even and reconnects at the surface. Positional +pairs, such as `deltar` in the matching and `RaySolveResult.Δ`, are always ordered +``(\Delta_+, \Delta_-)``, as in GWP2016 Eq. (38); `InnerLayerResponse` names them +`interchange` and `tearing`. ## Numerical method @@ -239,14 +244,14 @@ reproduces the Fortran `rmatch deltac` solver to ``\sim 10^{-8}``: | quantity | `:galerkin` (= Fortran to ``10^{-8}``) | `:ray` | |:---------|:---------------------------------------|:-------| -| ``\Delta_\mathrm{odd}`` | ``3.698368\times 10^{4}`` | ``3.69789\times 10^{4}`` | -| ``\Delta_\mathrm{even}`` | ``14.759721`` | ``14.759715`` | +| ``\Delta_+`` (interchange) | ``3.698368\times 10^{4}`` | ``3.69789\times 10^{4}`` | +| ``\Delta_-`` (tearing) | ``14.759721`` | ``14.759715`` | -The large ``\lvert\Delta_\mathrm{odd}\rvert \sim 4\times10^{4}`` means this +The large ``\lvert\Delta_+\rvert \sim 4\times10^{4}`` means this operating point sits near a pole of ``\Delta(Q)``, where every solver's error is amplified by the pole geometry; the ``1.3\times10^{-4}`` -`:galerkin`↔`:ray` difference in ``\Delta_\mathrm{odd}`` (versus -``4\times10^{-7}`` in ``\Delta_\mathrm{even}``) is consistent with that +`:galerkin`↔`:ray` difference in ``\Delta_+`` (versus +``4\times10^{-7}`` in ``\Delta_-``) is consistent with that amplification, not a defect of either backend. **Physical benchmark on the imaginary axis.** On the ``q=4`` rational-surface @@ -256,15 +261,15 @@ entirely beyond `:galerkin`: | quantity | value at ``Q = 500i`` | |:---------|:----------------------| -| ``\Delta_\mathrm{odd}`` | ``2.4720 + 13.3540\,i`` | -| ``\Delta_\mathrm{even}`` | ``0.13750 + 0.74275\,i`` | +| ``\Delta_+`` (interchange) | ``2.4720 + 13.3540\,i`` | +| ``\Delta_-`` (tearing) | ``0.13750 + 0.74275\,i`` | **Convergence and contour invariance.** Because ``\Delta`` is an analytic invariant of the contour angle, re-solving with each numerical knob perturbed on an independent axis ([`delta_convergence`](@ref InnerLayer.delta_convergence)) gives an honest error bar: at ``Q = 500i`` the worst-case spread across all knobs is ``\sim 5\times10^{-6}`` -for ``\Delta_\mathrm{odd}`` and ``\sim 6\times10^{-7}`` for -``\Delta_\mathrm{even}``. That is a single-machine error bar: across +for ``\Delta_+`` and ``\sim 6\times10^{-7}`` for +``\Delta_-``. That is a single-machine error bar: across machines/BLAS builds the absolute values reproduce to ``\sim 10^{-5}`` relative (the damped-zone implicit solves carry platform-dependent structured roundoff), which is why the table above quotes five significant figures. @@ -286,11 +291,11 @@ using GeneralizedPerturbedEquilibrium.InnerLayer p = q4_surface_benchmark() # GGJParameters for the q=4 benchmark surface γ = 500im * GGJ.q0(p) # physical rate placing Q on the imaginary axis at 500i -Δ = solve_inner(GGJModel(), p, γ) # (Δ_odd, Δ_even) with the default :ray backend +Δ = solve_inner(GGJModel(), p, γ) # Δ.interchange, Δ.tearing with the default :ray backend # Full result (raw Δ, contour, mesh, nodal solution, boundary conditioning) via solve_ray: res = solve_ray(p, GGJ.inner_Q(p, γ)) -res.Δ, res.breaks, res.bc_cond +res.Δ, res.breaks, res.bc_cond # res.Δ = (Δ₊, Δ₋) = (interchange, tearing) ``` ## API Reference diff --git a/regression-harness/cases/ggj_ray_q500i.toml b/regression-harness/cases/ggj_ray_q500i.toml index f5722ee4d..0ccb2ac23 100644 --- a/regression-harness/cases/ggj_ray_q500i.toml +++ b/regression-harness/cases/ggj_ray_q500i.toml @@ -1,7 +1,7 @@ -# Regression case: GGJ inner-layer rotated-ray collocation backend at Q = 500i. +# Regression case: GGJ inner-layer rotated-ray backend at Q = 500i. # A "computed" case (kind = "computed", no example_dir) that calls solve_inner with the # :ray backend on the physical q=4 benchmark surface at Q = 500i — a regime beyond the -# :galerkin backend — and tracks the Δ_odd / Δ_even matching coefficients. Guards the +# :galerkin backend — and tracks the interchange (Δ₊) / tearing (Δ₋) matching coefficients. Guards the # rotated-ray solver (and its extended-precision damped-zone march) against numerical # drift across changes. Each [quantities.*] block names an HDF5 path in the computed # output, how to extract it, and the noise floor for diffs. @@ -10,40 +10,40 @@ name = "ggj_ray_q500i" description = "GGJ inner-layer :ray backend, q=4 surface, Q = 500i (beyond :galerkin)" kind = "computed" -# Δ_odd / Δ_even from solve_inner(GGJModel(:ray), q4_surface_benchmark(), 500im·Q₀). +# interchange (Δ₊) / tearing (Δ₋) from solve_inner(GGJModel(:ray), q4_surface_benchmark(), 500im·Q₀). # Complex-valued; both real and imaginary parts are tracked separately. # noise_threshold 1e-4 (absolute): the extended-precision damped-zone march carries # BLAS/platform-dependent structured roundoff at the ~1e-4 absolute level on these # O(10) components (~1e-5 relative); a tighter floor flags phantom cross-machine drift. -[quantities.delta_odd_real] -h5path = "ggj/delta_odd_real" +[quantities.delta_interchange_real] +h5path = "ggj/delta_interchange_real" type = "real_scalar" extract = "value" -label = "Re(Δ_odd)" +label = "Re(Δ₊ interchange)" noise_threshold = 1e-4 order = 10 -[quantities.delta_odd_imag] -h5path = "ggj/delta_odd_imag" +[quantities.delta_interchange_imag] +h5path = "ggj/delta_interchange_imag" type = "real_scalar" extract = "value" -label = "Im(Δ_odd)" +label = "Im(Δ₊ interchange)" noise_threshold = 1e-4 order = 11 -[quantities.delta_even_real] -h5path = "ggj/delta_even_real" +[quantities.delta_tearing_real] +h5path = "ggj/delta_tearing_real" type = "real_scalar" extract = "value" -label = "Re(Δ_even)" +label = "Re(Δ₋ tearing)" noise_threshold = 1e-4 order = 12 -[quantities.delta_even_imag] -h5path = "ggj/delta_even_imag" +[quantities.delta_tearing_imag] +h5path = "ggj/delta_tearing_imag" type = "real_scalar" extract = "value" -label = "Im(Δ_even)" +label = "Im(Δ₋ tearing)" noise_threshold = 1e-4 order = 13 diff --git a/regression-harness/cases/ggj_reference.toml b/regression-harness/cases/ggj_reference.toml index d6c863ea0..bcf1b76e3 100644 --- a/regression-harness/cases/ggj_reference.toml +++ b/regression-harness/cases/ggj_reference.toml @@ -1,42 +1,42 @@ # Regression case: GGJ inner-layer Galerkin solver reference (Glasser & Wang 2020, Eq. 55). # A "computed" case (kind = "computed", no example_dir) that calls solve_inner directly and -# tracks the Δ_odd / Δ_even inner-layer coefficients. Each [quantities.*] block names an +# tracks the interchange (Δ₊) / tearing (Δ₋) inner-layer coefficients. Each [quantities.*] block names an # HDF5 path in the computed output, how to extract it, and the noise floor for diffs. [case] name = "ggj_reference" description = "GGJ inner-layer Galerkin solver, Glasser & Wang 2020 Eq. 55 with physical τ_A, τ_R, 1 kHz rotation (Q ≈ 0.22i)" kind = "computed" -# Δ_odd / Δ_even from solve_inner(GGJModel(:galerkin), glasser_wang_2020_eq55(; taua=2.11226e-7, taur=0.968219), 2πi·10³) -[quantities.delta_odd_real] -h5path = "ggj/delta_odd_real" +# interchange (Δ₊) / tearing (Δ₋) from solve_inner(GGJModel(:galerkin), glasser_wang_2020_eq55(; taua=2.11226e-7, taur=0.968219), 2πi·10³) +[quantities.delta_interchange_real] +h5path = "ggj/delta_interchange_real" type = "real_scalar" extract = "value" -label = "Re(Δ_odd)" +label = "Re(Δ₊ interchange)" noise_threshold = 1e-10 order = 10 -[quantities.delta_odd_imag] -h5path = "ggj/delta_odd_imag" +[quantities.delta_interchange_imag] +h5path = "ggj/delta_interchange_imag" type = "real_scalar" extract = "value" -label = "Im(Δ_odd)" +label = "Im(Δ₊ interchange)" noise_threshold = 1e-10 order = 11 -[quantities.delta_even_real] -h5path = "ggj/delta_even_real" +[quantities.delta_tearing_real] +h5path = "ggj/delta_tearing_real" type = "real_scalar" extract = "value" -label = "Re(Δ_even)" +label = "Re(Δ₋ tearing)" noise_threshold = 1e-10 order = 12 -[quantities.delta_even_imag] -h5path = "ggj/delta_even_imag" +[quantities.delta_tearing_imag] +h5path = "ggj/delta_tearing_imag" type = "real_scalar" extract = "value" -label = "Im(Δ_even)" +label = "Im(Δ₋ tearing)" noise_threshold = 1e-10 order = 13 diff --git a/regression-harness/src/runner.jl b/regression-harness/src/runner.jl index 19cfc19e0..b9e4432e5 100644 --- a/regression-harness/src/runner.jl +++ b/regression-harness/src/runner.jl @@ -100,12 +100,9 @@ elapsed = time() - t_start # Self-contained computation for the GGJ inner-layer reference benchmark. # Runs the Galerkin solver on the Glasser & Wang 2020 Eq. 55 coefficients with physical # time scales (the q = 4 benchmark surface's τ_A, τ_R) at a 1 kHz rotation, γ = 2πi·10³ s⁻¹ -# (Q ≈ 0.22i, where the stock Galerkin matching is accurate), and writes (Δ_odd, Δ_even) -# into a small HDF5 file at ARGS[1]. +# (Q ≈ 0.22i, where the stock Galerkin matching is accurate), and writes the interchange (Δ₊) +# and tearing (Δ₋) matching data into a small HDF5 file at ARGS[1]. # Runtime and environment are written to ARGS[2] by the shared run-info epilogue. -# `solve_inner` returns the named-field `InnerLayerResponse`; the historical -# delta_odd / delta_even slots map to interchange / tearing respectively, which -# preserves the numeric identity of each tracked quantity. const COMPUTED_GGJ_SCRIPT_TEMPLATE = """ using Pkg %INSTANTIATE% @@ -118,10 +115,10 @@ t_start = time() Δ = solve_inner(GGJModel(solver=:galerkin), p, γ) elapsed = time() - t_start h5open(ARGS[1], "w") do fid - fid["ggj/delta_odd_real"] = real(Δ.interchange) - fid["ggj/delta_odd_imag"] = imag(Δ.interchange) - fid["ggj/delta_even_real"] = real(Δ.tearing) - fid["ggj/delta_even_imag"] = imag(Δ.tearing) + fid["ggj/delta_interchange_real"] = real(Δ.interchange) + fid["ggj/delta_interchange_imag"] = imag(Δ.interchange) + fid["ggj/delta_tearing_real"] = real(Δ.tearing) + fid["ggj/delta_tearing_imag"] = imag(Δ.tearing) end %RUNINFO% """ @@ -130,7 +127,6 @@ end # :galerkin backend. Builds the physical rate γ = 500i·Q₀ so inner_Q lands exactly on the # imaginary axis at 500i, then writes the parity matching data. Runtime and environment are # written to ARGS[2] by the shared run-info epilogue. -# As in the galerkin template, the delta_odd / delta_even slots map to interchange / tearing. const COMPUTED_GGJ_RAY_SCRIPT_TEMPLATE = """ using Pkg %INSTANTIATE% @@ -143,10 +139,10 @@ t_start = time() Δ = solve_inner(GGJModel(solver=:ray), p, γ) elapsed = time() - t_start h5open(ARGS[1], "w") do fid - fid["ggj/delta_odd_real"] = real(Δ.interchange) - fid["ggj/delta_odd_imag"] = imag(Δ.interchange) - fid["ggj/delta_even_real"] = real(Δ.tearing) - fid["ggj/delta_even_imag"] = imag(Δ.tearing) + fid["ggj/delta_interchange_real"] = real(Δ.interchange) + fid["ggj/delta_interchange_imag"] = imag(Δ.interchange) + fid["ggj/delta_tearing_real"] = real(Δ.tearing) + fid["ggj/delta_tearing_imag"] = imag(Δ.tearing) end %RUNINFO% """ diff --git a/src/ForceFreeStates/Matching/MatchProblem.jl b/src/ForceFreeStates/Matching/MatchProblem.jl index a40c5c9f3..972804c6e 100644 --- a/src/ForceFreeStates/Matching/MatchProblem.jl +++ b/src/ForceFreeStates/Matching/MatchProblem.jl @@ -126,10 +126,10 @@ function _compute_match(prob::MatchProblem, model::InnerLayer.GGJModel) # Layer-center field weight per parity (match.f intotsol_b). pen = zeros(ComplexF64, msing, 2) inner_psi = Vector{Vector{Float64}}(undef, msing) # ψ_s ± X·dψdx, ascending - inner_odd = Vector{Vector{ComplexF64}}(undef, msing) # Ξ₁, odd about ψ_s - inner_even = Vector{Vector{ComplexF64}}(undef, msing) # Ξ₂, even - inner_bodd = Vector{Vector{ComplexF64}}(undef, msing) # b^ψ from Ψ₁, even - inner_beven = Vector{Vector{ComplexF64}}(undef, msing) # b^ψ from Ψ₂, odd + inner_odd = Vector{Vector{ComplexF64}}(undef, msing) # Ξ₋, odd about ψ_s + inner_even = Vector{Vector{ComplexF64}}(undef, msing) # Ξ₊, even + inner_bodd = Vector{Vector{ComplexF64}}(undef, msing) # b^ψ from Ψ₋, even + inner_beven = Vector{Vector{ComplexF64}}(undef, msing) # b^ψ from Ψ₊, odd inner_params = Vector{InnerLayer.GGJParameters}(undef, msing) profiles = true for i in 1:msing @@ -138,15 +138,15 @@ function _compute_match(prob::MatchProblem, model::InnerLayer.GGJModel) inner_params[i] = params γ = 2π * im * nn * prob.rotation[i] # forced eigenvalue, f in Hz rpec_eig[i] = γ - inner = InnerLayer.solve_inner_profile(model, params, γ) + inner = InnerLayer.solve_inner_profile(model, params, γ) # parity columns (Δ₊, Δ₋) deltar[i, 1] = inner.Δ[1] deltar[i, 2] = inner.Δ[2] profΨ, profΞ, xg = inner.Ψ, inner.Ξ, inner.x resc = inner.rescale # inner big-branch amplitude → outer δψ normalization # b_m = 2πi·χ₁·(m−nq)·ξ_m with m−nq = −n·q′·dψdx·X and Ψ = XΞ (GWP2016 Eq. 16) ⇒ b_m = scale·resc·Ψ. scale = -2π * chi1 * im * nn * sings[i].q1 * inner.dψdx - pen[i, 1] = scale * profΨ[1, 1] * resc # X = 0, parity 1 - pen[i, 2] = scale * profΨ[1, 2] * resc # parity 2 (Ψ(0) = 0) + pen[i, 1] = scale * profΨ[1, 1] * resc # X = 0, even parity (Ψ(0) = 0) + pen[i, 2] = scale * profΨ[1, 2] * resc # odd parity # A backend returning only layer-center values (real-ψ profiles not requested) skips the inner profiles. if length(xg) == 1 profiles = false @@ -154,18 +154,18 @@ function _compute_match(prob::MatchProblem, model::InnerLayer.GGJModel) end xvar = xg .* inner.dψdx # X → ψ distance inner_psi[i] = vcat(reverse(sings[i].psifac .- xvar), sings[i].psifac .+ xvar) - inner_odd[i] = resc .* vcat(reverse(.-profΞ[:, 1]), profΞ[:, 1]) - inner_even[i] = resc .* vcat(reverse(profΞ[:, 2]), profΞ[:, 2]) - inner_bodd[i] = (scale * resc) .* vcat(reverse(profΨ[:, 1]), profΨ[:, 1]) - inner_beven[i] = (scale * resc) .* vcat(reverse(.-profΨ[:, 2]), profΨ[:, 2]) + inner_odd[i] = resc .* vcat(reverse(.-profΞ[:, 2]), profΞ[:, 2]) + inner_even[i] = resc .* vcat(reverse(profΞ[:, 1]), profΞ[:, 1]) + inner_bodd[i] = (scale * resc) .* vcat(reverse(profΨ[:, 2]), profΨ[:, 2]) + inner_beven[i] = (scale * resc) .* vcat(reverse(.-profΨ[:, 1]), profΨ[:, 1]) end cout, cin, residual = _match_system(dp.raw, dp.coil, deltar) - # Penetrated field at each layer center (match.f intotsol_b). + # Penetrated field at each layer center (match.f intotsol_b); cin rows per surface are (d₊, d₋). bpen = zeros(ComplexF64, msing, mcoil) for i in 1:msing, j in 1:mcoil - bpen[i, j] = pen[i, 1] * cin[2i, j] + pen[i, 2] * cin[2i-1, j] + bpen[i, j] = pen[i, 1] * cin[2i-1, j] + pen[i, 2] * cin[2i, j] end # Matched inner ξ_ψ and b^ψ per coil: odd parity × cin[2i], even × cin[2i-1] (match.f intotsol). diff --git a/src/ForceFreeStates/Matching/ResonantMatch.jl b/src/ForceFreeStates/Matching/ResonantMatch.jl index 921095186..bb96858dc 100644 --- a/src/ForceFreeStates/Matching/ResonantMatch.jl +++ b/src/ForceFreeStates/Matching/ResonantMatch.jl @@ -10,7 +10,7 @@ fields are empty when the solve kept no Galerkin basis; the inner fields are emp ## Fields - `cout`, `cin`: `(2msing, ncoil)` outer and inner coefficients. - - `deltar`: `(msing, 2)` inner-layer Δ per surface and parity. + - `deltar`: `(msing, 2)` inner-layer Δ per surface, columns (Δ₊, Δ₋) = (interchange, tearing). - `rpec_eig`: forced eigenvalue γ = 2πi·n·f per surface. - `residual`: relative residual of the linear solve. - `bpen`: `(msing, ncoil)` penetrated resonant field at each layer center. @@ -51,8 +51,8 @@ function _match_system(dp_raw::AbstractMatrix, dp_coil::AbstractMatrix, deltar:: idx2 = 2ising idx3 = idx1 + 2msing idx4 = idx2 + 2msing - delta1 = deltar[ising, 1] - delta2 = deltar[ising, 2] + delta1 = deltar[ising, 1] # Δ₊; rows idx3, idx4 of cin are d₊, d₋ (GWP2016 Eqs. 36–37) + delta2 = deltar[ising, 2] # Δ₋ mat[idx1, idx1] = 1 mat[idx2, idx2] = 1 mat[idx1, idx3] = -1 @@ -112,7 +112,7 @@ const MATCH_H5_ANNOTATIONS = [ "SingularSurfaces/Match/cin" => (; long_name="inner-region matching coefficients per surface parity, per unit coil-response column", dims=("surface_parity", "coil")), "SingularSurfaces/Match/Delta_r" => - (; long_name="inner-layer Δ per surface and parity (deltac convention)", dims=("surface", "parity")), + (; long_name="inner-layer Δ per surface and parity, (Δ₊ interchange, Δ₋ tearing)", dims=("surface", "parity")), "SingularSurfaces/Match/bpen" => (; long_name="penetrated resonant field b^ψ at each layer center, per unit coil-response column", dims=("surface", "coil")), "SingularSurfaces/Match/reconnected_flux" => diff --git a/src/InnerLayer/GGJ/GGJ.jl b/src/InnerLayer/GGJ/GGJ.jl index 6366f3481..941a319a4 100644 --- a/src/InnerLayer/GGJ/GGJ.jl +++ b/src/InnerLayer/GGJ/GGJ.jl @@ -12,8 +12,9 @@ # and the same Hermite assembly with a point far-field condition; # robust to |Q| ~ 500 on/near the imaginary axis # -# They return the parity-projected matching data -# `(Δ_odd, Δ_even)` of GWP2016 Eqs. (34)–(35) in the same (deltac) convention. +# They return the parity-projected matching data Δ± of GWP2016 Eqs. (34)–(35). Parity is +# that of the displacement Ξ: Δ₊ (even) is the interchange channel, Δ₋ (odd) the tearing +# channel; positional pairs are always ordered (Δ₊, Δ₋), as in GWP2016 Eq. (38). # # Equation references throughout this module use two source papers: # diff --git a/src/InnerLayer/GGJ/Galerkin.jl b/src/InnerLayer/GGJ/Galerkin.jl index f7557b609..88df54feb 100644 --- a/src/InnerLayer/GGJ/Galerkin.jl +++ b/src/InnerLayer/GGJ/Galerkin.jl @@ -732,11 +732,10 @@ function _parity_bcs_and_solve!(ws::GalerkinWorkspace, params::GGJParameters, Q: end end - # Apply parity BCs for each solution (isol=1: odd, isol=2: even). The - # inner equations have reflection symmetry about X=0 (GWP2016 Sec. III): - # one solution has even Ξ, Υ and odd Ψ, the other odd Ξ, Υ and even Ψ. - # Imposing both at X=0 gives the two parities that each contribute a Δ for - # outer-region matching (the Δ_odd, Δ_even of GWP2016 Eqs. 34–35). + # Apply parity BCs for each solution. The inner equations have reflection symmetry + # about X=0 (GWP2016 Sec. III); parity is that of the displacement Ξ (GWP2016 Eq. 34): + # isol=1 is even (+, interchange: even Ξ, Υ, odd Ψ), isol=2 odd (−, tearing: odd Ξ, Υ, + # even Ψ). Each contributes a Δ± for outer-region matching (GWP2016 Eqs. 34–35). # For each isol, build a modified local # matrix for ip=0..1 of cell 1, then write it into the global matrix. for isol in 1:2 @@ -744,37 +743,36 @@ function _parity_bcs_and_solve!(ws::GalerkinWorkspace, params::GGJParameters, Q: for ipert in 1:mpert i = cell1.map[ipert, 1] # ip=0 DOFs if i > ws.ndim - continue end for jj in max(1, i - ws.kl):min(ws.ndim, i + ws.kl) ws.mat[offset+i-jj, jj, isol] = 0 end end - # Odd parity (isol=1): Ψ'(0)=0, Ξ(0)=0, Υ(0)=0 - # → row=Ψ(ip=0), col=Ψ(ip=1): A[map[1,1], map[1,2]] = 1 - # → row=Ξ(ip=0), col=Ξ(ip=0): A[map[2,1], map[2,1]] = 1 - # → row=Υ(ip=0), col=Υ(ip=0): A[map[3,1], map[3,1]] = 1 - # Even parity (isol=2): Ψ(0)=0, Ξ'(0)=0, Υ'(0)=0 + # Even parity (isol=1): Ψ(0)=0, Ξ'(0)=0, Υ'(0)=0 # → row=Ψ(ip=0), col=Ψ(ip=0): A[map[1,1], map[1,1]] = 1 # → row=Ξ(ip=0), col=Ξ(ip=1): A[map[2,1], map[2,2]] = 1 # → row=Υ(ip=0), col=Υ(ip=1): A[map[3,1], map[3,2]] = 1 + # Odd parity (isol=2): Ψ'(0)=0, Ξ(0)=0, Υ(0)=0 + # → row=Ψ(ip=0), col=Ψ(ip=1): A[map[1,1], map[1,2]] = 1 + # → row=Ξ(ip=0), col=Ξ(ip=0): A[map[2,1], map[2,1]] = 1 + # → row=Υ(ip=0), col=Υ(ip=0): A[map[3,1], map[3,1]] = 1 if isol == 1 i = cell1.map[1, 1] - j = cell1.map[1, 2] + j = cell1.map[1, 1] ws.mat[offset+i-j, j, isol] = 1 for ipert in 2:3 i = cell1.map[ipert, 1] - j = cell1.map[ipert, 1] + j = cell1.map[ipert, 2] ws.mat[offset+i-j, j, isol] = 1 end else i = cell1.map[1, 1] - j = cell1.map[1, 1] + j = cell1.map[1, 2] ws.mat[offset+i-j, j, isol] = 1 for ipert in 2:3 i = cell1.map[ipert, 1] - j = cell1.map[ipert, 2] + j = cell1.map[ipert, 1] ws.mat[offset+i-j, j, isol] = 1 end end @@ -808,7 +806,7 @@ far-field condition imposed at the last node instead of resonant/extension cells v = Us + Δ·Ub + c₁E₁ + c₂E₂, with Us, Ub, E given as (Ψ, Ξ, Υ, Ψ', Ξ', Υ') in x-derivatives. The last node's six DOFs are replaced by (Δ, c₁, c₂) and tested in the same three directions, as the extension cell does for the stock backend. Returns the raw Δ and decaying-pair coefficients per parity -(isol = 1 odd, 2 even); `ws.sol` holds the full nodal solution afterwards. +(isol = 1 even/Δ₊, 2 odd/Δ₋); `ws.sol` holds the full nodal solution afterwards. """ function _assemble_and_solve_point!(ws::GalerkinWorkspace, params::GGJParameters, Q::ComplexF64, θ::Float64, Us::Vector{ComplexF64}, Ub::Vector{ComplexF64}, E::Matrix{ComplexF64}; nq::Int=6) @@ -881,7 +879,7 @@ end # Hermite DOFs over the bulk (Hermite) cells. The thin CT_EXT / CT_RES # matching cells near xmax are skipped (their solution is carried by the # asymptotic emap DOF, not the Hermite basis). Returns the grid `x` and the -# three fields for both parities (columns: 1 = odd, 2 = even). +# three fields for both parities (columns: 1 = even/Δ₊, 2 = odd/Δ₋). # ----------------------------------------------------------------------- function _solution_profile(ws::GalerkinWorkspace; npc::Int=10) mpert = 3 @@ -926,7 +924,7 @@ end # Stock Galerkin solve shared by `solve_inner` and `solve_inner_profile`. The matching data are the # resonant cell's emap DOF, the coefficient of the large resonant solution (GWP2016 Eqs. 34–35), per -# parity isol = 1 (odd), 2 (even); returns them rescaled, with the solved workspace. +# parity isol = 1 (even, Δ₊), 2 (odd, Δ₋); returns them rescaled, with the solved workspace. function _galerkin_solve(params::GGJParameters, γ::Number; kmax::Int=8, nx::Int=512, nq::Int=4, pfac::Float64=1.0, cutoff::Int=5, xfac::Float64=1.0, tol_res::Float64=1e-5) @@ -949,7 +947,7 @@ numerics/kwargs as `solve_inner(GGJModel(; solver=:galerkin), ...)`. function solve_inner_profile(::_BareGGJ{:galerkin}, params::GGJParameters, γ::Number; kwargs...) Δ, ws = _galerkin_solve(params, γ; kwargs...) prof = _solution_profile(ws) - return (; Δ=SVector(Δ[2], Δ[1]), x=prof.x, Ψ=prof.Ψ, Ξ=prof.Ξ, _profile_conversions(params)...) + return (; Δ=Δ, x=prof.x, Ψ=prof.Ψ, Ξ=prof.Ξ, _profile_conversions(params)...) end """ @@ -963,12 +961,10 @@ element (Galerkin) method (GWP2016 Sec. III), in the "resonant + noexp + inps" configuration. Returns the parity-projected matching data (GWP2016 Eqs. 34–35) with the -`X₀^{2√(−D_I)}` physical rescaling applied, as an `InnerLayerResponse` whose -`tearing`/`interchange` fields are the isol=1/isol=2 element solutions -respectively — no parity swap (see the boundary-condition block above for the -parity derivation). +`X₀^{2√(−D_I)}` physical rescaling applied, as an `InnerLayerResponse`: +`interchange` is the even-parity Δ₊ (isol = 1), `tearing` the odd-parity Δ₋ (isol = 2). """ function solve_inner(::_BareGGJ{:galerkin}, params::GGJParameters, γ::Number; kwargs...) Δ, _ = _galerkin_solve(params, γ; kwargs...) - return InnerLayerResponse(Δ[1], Δ[2]) + return InnerLayerResponse(; interchange=Δ[1], tearing=Δ[2]) end diff --git a/src/InnerLayer/GGJ/Ray.jl b/src/InnerLayer/GGJ/Ray.jl index 57684ace2..7550eb84b 100644 --- a/src/InnerLayer/GGJ/Ray.jl +++ b/src/InnerLayer/GGJ/Ray.jl @@ -391,9 +391,9 @@ Output of [`solve_ray`](@ref). ## Fields - - `Δ`: rescaled matching data in the deltac output ordering (index 1 ↔ even-BC solution, - 2 ↔ odd-BC solution, the same swap deltac_solve applies). - - `Δraw`: (isol = 1, isol = 2) in raw inps normalization, before `rescale_delta`. + - `Δ`: rescaled matching data (Δ₊, Δ₋) = (interchange, tearing), the even (isol = 1) and + odd (isol = 2) parities of the displacement Ξ. + - `Δraw`: the same pair in raw inps normalization, before `rescale_delta`. - `cexp`: decaying-pair coefficients (c₁, c₂) at s_m, one column per parity. - `Q`, `θ`: scaled eigenvalue and contour angle. - `S`: series radius where the far-field data were taken. @@ -423,7 +423,7 @@ end cfl=0.2, min_cells=1024, nq=6, verbose=false, kwargs...) -> RaySolveResult Solve the GGJ inner-layer problem on the rotated ray x = e^{iθ}s. -`Δ` follows the deltac output convention (swap + `rescale_delta`), directly +`Δ` is the rescaled pair (Δ₊, Δ₋) = (interchange, tearing), directly comparable to the `:galerkin` backend. θ = 0 reproduces a real-axis solve; `S` defaults to the inps series-residual radius (`pick_smax`); `cfl`, `min_cells` set the Hermite grid ([`ray_breaks`](@ref)) and `nq` its quadrature; remaining keywords are march @@ -492,8 +492,7 @@ function solve_ray(params::GGJParameters, Q::ComplexF64; verbose && @printf(" BVP: %d Hermite cells on [0, %.4g], Δraw[1] = %.6e %+.6eim\n", length(breaks) - 1, Sbvp, real(Δraw[1]), imag(Δraw[1])) - Δswapped = SVector{2,ComplexF64}(Δraw[2], Δraw[1]) # deltac_solve convention - Δ = rescale_delta(Δswapped, params) + Δ = rescale_delta(Δraw, params) return RaySolveResult(Δ, Δraw, cexp, Q, θ, Sv, series_ok, bc_cond, breaks, cfl, min_cells, ws) end @@ -506,16 +505,15 @@ solve_ray(params::GGJParameters, Q::Number; kwargs...) = -> InnerLayerResponse Rotated-ray backend: converts γ via `inner_Q`, forwards keywords to -[`solve_ray`](@ref), and returns the parity-projected matching data. The -`solve_ray` pair is ordered `(Δ₁, Δ₂) = (interchange, tearing)`, so the two -channels are swapped into the named fields of [`InnerLayerResponse`](@ref). +[`solve_ray`](@ref), and returns the parity-projected matching data (Δ₊, Δ₋) as the +`interchange` and `tearing` fields of [`InnerLayerResponse`](@ref). Preferred for |Q| ≳ 1 and near the imaginary axis; use `solve_ray` directly when the full [`RaySolveResult`](@ref) is wanted. `real_profiles` is a profile-only model option (see `solve_inner_profile`) and is ignored here. """ function solve_inner(::_BareGGJ{:ray}, params::GGJParameters, γ::Number; real_profiles::Bool=false, kwargs...) res = solve_ray(params, inner_Q(params, γ); kwargs...) - return InnerLayerResponse(res.Δ[2], res.Δ[1]) + return InnerLayerResponse(; interchange=res.Δ[1], tearing=res.Δ[2]) end """ @@ -528,7 +526,7 @@ layer-center fields come from the solve at θ = arg(Q)/4; x = 0 lies on every co Ψ(0), Ξ(0) there are the real-axis values. By default only those center values are returned (`x = [0.0]`, one-row `Ψ`, `Ξ`; `certΔ = NaN`), which is all the penetrated field needs. With `real_profiles = true` the fields across the layer come from an extra θ = 0 -re-solve on the real axis, and the θ = 0 vs θ = arg(Q)/4 Δ agreement is returned as `certΔ` +re-solve on the real axis, and the θ = 0 vs θ = arg(Q)/4 agreement of Δ₊ is returned as `certΔ` (a runtime certificate; warns above `certify_rtol`). `npc` sets the profile points per mesh cell; extra keywords forward to [`solve_ray`](@ref) (θ is fixed by the method — do not pass it). """ @@ -551,7 +549,7 @@ end solution_profile(res::RaySolveResult; npc=8) -> (; s, x, Ψ, Ξ, Υ) Reconstruct (Ψ, Ξ, Υ) on the solution contour from the Hermite nodal solution, `npc` -points per cell; each field is `npts × 2` with columns (odd, even) and `x = e^{iθ}s`. +points per cell; each field is `npts × 2` with columns (even, odd) as in `Δ`, and `x = e^{iθ}s`. For rotated solves the fields live on the ray — continuation back to real x is a separate (unstable) problem, by design. """ @@ -592,7 +590,7 @@ end Error bar for the matching data: solve at the baseline, then re-solve with each numerical knob perturbed on an independent axis (contour angle θ, mesh resolution, series order/radius, march tolerance, handoff radius, purification e-folds — see -`variations` below) and report the relative change of (Δ₁, Δ₂) per knob. θ is perturbed +`variations` below) and report the relative change of (Δ₊, Δ₋) per knob. θ is perturbed outward only: inward moves toward the x² ≈ −Q²(G+KF) pseudo-resonance and measures the perturbed solve, not the baseline. `spread` is the per-parity worst case over all knobs. """ @@ -609,7 +607,7 @@ function delta_convergence(params::GGJParameters, Q::ComplexF64; verbose::Bool=t table = NamedTuple[] spread = MVector{2,Float64}(0.0, 0.0) verbose && @printf("Δ convergence check, Q = %s:\n", string(Q)) - verbose && @printf(" baseline: Δ₁ = %+.8e %+.8eim, Δ₂ = %+.8e %+.8eim\n", + verbose && @printf(" baseline: Δ₊ = %+.8e %+.8eim, Δ₋ = %+.8e %+.8eim\n", real(base.Δ[1]), imag(base.Δ[1]), real(base.Δ[2]), imag(base.Δ[2])) for (name, kw) in variations r = solve_ray(params, Q; kwargs..., kw...) @@ -618,9 +616,9 @@ function delta_convergence(params::GGJParameters, Q::ComplexF64; verbose::Bool=t spread[1] = max(spread[1], d1) spread[2] = max(spread[2], d2) push!(table, (; name, d1, d2)) - verbose && @printf(" %-16s δΔ₁ = %.2e δΔ₂ = %.2e\n", name, d1, d2) + verbose && @printf(" %-16s δΔ₊ = %.2e δΔ₋ = %.2e\n", name, d1, d2) end - verbose && @printf(" %-16s δΔ₁ = %.2e δΔ₂ = %.2e\n", "WORST CASE", spread[1], spread[2]) + verbose && @printf(" %-16s δΔ₊ = %.2e δΔ₋ = %.2e\n", "WORST CASE", spread[1], spread[2]) return (; Δ=base.Δ, spread=SVector(spread), base=base, table=table) end diff --git a/src/InnerLayer/GGJ/Shooting.jl b/src/InnerLayer/GGJ/Shooting.jl index 9bb00b054..8f36926d8 100644 --- a/src/InnerLayer/GGJ/Shooting.jl +++ b/src/InnerLayer/GGJ/Shooting.jl @@ -342,13 +342,9 @@ end Solve the GGJ inner-layer matching problem by stable backward shooting in the origin-diagonalized 4×4 basis. -Returns an `InnerLayerResponse(tearing, interchange)` with rescaling -applied. `_delta_from_c0` returns a `(Δ₁, Δ₂)` pair where `Δ₁` is the -**interchange** (anti-symmetric / W-odd) channel and `Δ₂` is the -**tearing** (symmetric / W-even) channel. We therefore map -`Δ₂ → tearing` and `Δ₁ → interchange` into the named fields, matching the -physics channel labels used by the Galerkin solver and by the -`InnerLayerResponse` docstring. +Returns an `InnerLayerResponse` with rescaling applied. `_delta_from_c0` returns the +pair (Δ₊, Δ₋) = (interchange, tearing): even and odd parity of the displacement Ξ +(Ψ odd and even), the same order as the other GGJ backends. Tolerances `reltol`/`abstol` are the integrator tolerances; `rtol_origin` controls the truncation error of the origin Frobenius series and the @@ -374,8 +370,7 @@ function solve_inner(::_BareGGJ{:shooting}, params::GGJParameters, γ::Number; Δ_raw = _delta_from_c0(c0, sys) Δ_rescaled = rescale_delta(Δ_raw, params) - # Δ_rescaled ≡ (Δ₁, Δ₂) = (interchange, tearing). - return InnerLayerResponse(Δ_rescaled[2], Δ_rescaled[1]) + return InnerLayerResponse(; interchange=Δ_rescaled[1], tearing=Δ_rescaled[2]) end solve_inner(::_BareGGJ{:shooting}, params::GGJParameters, γ::Real; kwargs...) = diff --git a/src/InnerLayer/InnerLayerInterface.jl b/src/InnerLayer/InnerLayerInterface.jl index 52e1b36ea..03ca65d76 100644 --- a/src/InnerLayer/InnerLayerInterface.jl +++ b/src/InnerLayer/InnerLayerInterface.jl @@ -35,25 +35,27 @@ the `Δ_{j,±}(γ)` of Glasser, Wang & Park, Phys. Plasmas **23**, 112506 # Fields - - `tearing` — the **odd-parity** matching coefficient (GWP Δ_+, the - "odd mode"). Corresponds to a flux perturbation W that is EVEN in x and - a velocity/temperature perturbation that is ODD — i.e., the + - `tearing` — the **odd-parity** matching coefficient Δ₋ (GWP2016 Eq. 34; Pletzer, + Bondeson & Dewar, J. Comput. Phys. 115, 530 (1994), Eqs. 87–89). Corresponds to a + flux perturbation W that is EVEN in x and a displacement/velocity/temperature + perturbation that is ODD — i.e., the reconnecting mode with a current sheet at the rational surface. This is the tearing drive that appears as Δ' in the classical constant-ψ tearing equation. Must be populated by every resistive inner-layer model. - - `interchange` — the **even-parity** matching coefficient (GWP Δ_−, the - "even mode"). Corresponds to W odd, N and Θ even — i.e., the + - `interchange` — the **even-parity** matching coefficient Δ₊. Corresponds to W odd, + N and Θ even — i.e., the non-reconnecting interchange/ballooning channel. Its dissipative piece in toroidal geometry is the Glasser, Greene & Johnson stabilization term that opposes tearing growth (Glasser, Greene & Johnson 1975; Lütjens-Bondeson-Roy 1993). Pressureless inner-layer models (e.g. SLAYER's Fitzpatrick Riccati) set this identically zero. -The naming follows the physics channel rather than a mathematical parity -label because `odd/even` carries different meanings across the literature -depending on whether you label by the parity of W (GWP paper convention) -or the parity of (N, Θ). Using `tearing` and `interchange` avoids ambiguity. +Parity labels follow GWP2016 and Pletzer, Bondeson & Dewar: the parity of the +displacement (Ξ, matched to the outer ξ), with + even and − odd. The fields are named +by the physics channel because the parity of the flux W is the opposite. Positional +pairs elsewhere in `InnerLayer` (e.g. the `Δ` of [`solve_inner_profile`](@ref)) are +ordered (Δ₊, Δ₋) = (interchange, tearing). """ struct InnerLayerResponse tearing::ComplexF64 @@ -85,10 +87,11 @@ profiles for the given `model` — everything an outer↔inner matching driver needs from the layer, so drivers never touch model internals. Returns a named tuple with at least: - - `Δ` — the same `(Δ_odd, Δ_even)` matching data as [`solve_inner`](@ref) + - `Δ` — the same matching data as [`solve_inner`](@ref), as the pair + (Δ₊, Δ₋) = (interchange, tearing) - `x` — real ascending grid in the model's stretched inner coordinate, `x ≥ 0` with the rational surface at `x = 0` - - `Ψ`, `Ξ` — `length(x) × 2` profiles, columns (odd, even) parity, in the + - `Ψ`, `Ξ` — `length(x) × 2` profiles, columns in the order of `Δ`, in the model's inner normalization: `Ψ` the normal-field (reconnected-flux) variable, `Ξ` the displacement - `dψdx` — conversion to poloidal-flux distance, `δψ = dψdx · x` diff --git a/src/InnerLayer/SLAYER/Riccati.jl b/src/InnerLayer/SLAYER/Riccati.jl index 87781259b..8f4e518c6 100644 --- a/src/InnerLayer/SLAYER/Riccati.jl +++ b/src/InnerLayer/SLAYER/Riccati.jl @@ -261,7 +261,7 @@ function solve_inner(::SLAYERModel{:fitzpatrick}, Δ::ComplexF64 = π / dW_end # Fitzpatrick / pressureless SLAYER has no interchange channel - # (the Δ_− / even-parity matching quantity is identically zero in + # (the Δ₊ / even-parity matching quantity is identically zero in # the pressureless limit), so populate only the tearing field. return InnerLayerResponse(Δ, zero(ComplexF64)) end diff --git a/src/Tearing/Dispersion/CoupledFullMatch.jl b/src/Tearing/Dispersion/CoupledFullMatch.jl index 9b0f136c9..6a4362d6f 100644 --- a/src/Tearing/Dispersion/CoupledFullMatch.jl +++ b/src/Tearing/Dispersion/CoupledFullMatch.jl @@ -171,7 +171,7 @@ function (mc::MultiSurfaceCouplingFull)(Q::Number) Q_k = Qc * (ref_tauk / sc.tauk) + 1im * mc.ntor * mc.rotation[k] resp = solve_inner(sc.model, sc.params, Q_k; mc.inner_kwargs...) - # delta1 = interchange (parity −), delta2 = tearing (parity +); named + # delta1 = interchange (parity +), delta2 = tearing (parity −); named # fields expose the two channels directly. sc.scale converts inner-basis # Δ to outer units (1.0 for GGJ since rescale_delta is applied inside # solve_inner; S^(1/3) for SLAYER). diff --git a/src/Tearing/Runner/run_slayer.jl b/src/Tearing/Runner/run_slayer.jl index f50f4101e..49a1af866 100644 --- a/src/Tearing/Runner/run_slayer.jl +++ b/src/Tearing/Runner/run_slayer.jl @@ -387,7 +387,7 @@ end Evaluate both parity channels of the GGJ inner-layer matching data at the complex normalized growth rate `Q` for each rational surface. Returns a vector of `(ising, tearing, interchange)` named tuples, where `tearing` -(GWP Δ_+) is the reconnecting channel and `interchange` (GWP Δ_−) the +(GWP Δ₋, odd) is the reconnecting channel and `interchange` (GWP Δ₊, even) the non-reconnecting Glasser-stabilization channel (see `InnerLayerResponse`). This is the supported GGJ diagnostic: both parity Δ's are physical and diff --git a/test/runtests_innerlayer.jl b/test/runtests_innerlayer.jl index 17dc3323e..b23624ebc 100644 --- a/test/runtests_innerlayer.jl +++ b/test/runtests_innerlayer.jl @@ -133,7 +133,7 @@ end Q = 5.0im conv = IL.delta_convergence(p, Q; verbose=false) Δ = IL.solve_inner(IL.GGJModel(; solver=:ray), p, Q * GGJ.q0(p)) - # conv.Δ is the raw solve_ray pair (Δ₁, Δ₂) = (interchange, tearing). + # conv.Δ is the solve_ray pair (Δ₊, Δ₋) = (interchange, tearing). @test conv.Δ[1] ≈ Δ.interchange rtol = 1e-6 # baseline == the plain solve @test conv.Δ[2] ≈ Δ.tearing rtol = 1e-6 @test maximum(conv.spread) < 1e-4 # honest error bar is small here @@ -146,7 +146,7 @@ end for model in (IL.GGJModel(; solver=:ray, real_profiles=true), IL.GGJModel(; solver=:galerkin)) prof = IL.solve_inner_profile(model, p, γ) # Δ agrees with the plain matching solve of the same backend (identical solve path). - # prof.Δ stays the positional pair (Δ₁, Δ₂) = (interchange, tearing) that feeds deltar. + # prof.Δ is the positional pair (Δ₊, Δ₋) = (interchange, tearing) that feeds deltar. Δ_plain = IL.solve_inner(model, p, γ) @test prof.Δ[1] ≈ Δ_plain.interchange rtol = 1e-12 @test prof.Δ[2] ≈ Δ_plain.tearing rtol = 1e-12 @@ -155,8 +155,8 @@ end @test prof.x[1] ≈ 0 atol = 1e-12 @test size(prof.Ψ) == (length(prof.x), 2) && size(prof.Ξ) == (length(prof.x), 2) @test all(isfinite, prof.Ψ) && all(isfinite, prof.Ξ) - # Parity at the layer center: Ψ(0) ≠ 0 odd-parity column, Ψ(0) = 0 even-parity column. - @test abs(prof.Ψ[1, 2]) < 1e-6 * abs(prof.Ψ[1, 1]) + # Parity at the layer center: Ψ(0) = 0 in the even (Δ₊) column, Ψ(0) ≠ 0 in the odd (Δ₋) one. + @test abs(prof.Ψ[1, 1]) < 1e-6 * abs(prof.Ψ[1, 2]) # Conversion factors match their GGJ definitions. @test prof.dψdx ≈ GGJ.x0(p) / p.v1 @test prof.rescale ≈ (p.v1 / GGJ.x0(p))^(0.5 + GGJ.p1(p)) @@ -172,7 +172,7 @@ end full = IL.solve_inner_profile(IL.GGJModel(; solver=:ray, real_profiles=true), p, γi) @test c.x == [0.0] && size(c.Ψ) == (1, 2) && isnan(c.certΔ) @test c.Δ == full.Δ - @test c.Ψ[1, 1] ≈ full.Ψ[1, 1] rtol = 1e-6 - @test c.Ξ[1, 2] ≈ full.Ξ[1, 2] rtol = 1e-6 + @test c.Ψ[1, 2] ≈ full.Ψ[1, 2] rtol = 1e-6 + @test c.Ξ[1, 1] ≈ full.Ξ[1, 1] rtol = 1e-6 @test full.certΔ < 1e-5 end From c6656e611042e061dc71324a21dc5b4f5d8d2811 Mon Sep 17 00:00:00 2001 From: Matthew Pharr Date: Mon, 19 Oct 2026 14:12:37 +0200 Subject: [PATCH 05/12] InnerLayer - DOCS - Trim the GGJ comments and inner-layer page to code behavior and paper pointers --- docs/src/inner_layer.md | 251 +++++++++------------------------ src/InnerLayer/GGJ/Galerkin.jl | 199 +++++--------------------- src/InnerLayer/GGJ/Ray.jl | 189 ++++++------------------- 3 files changed, 147 insertions(+), 492 deletions(-) diff --git a/docs/src/inner_layer.md b/docs/src/inner_layer.md index 20dc7fde5..42295b6a6 100644 --- a/docs/src/inner_layer.md +++ b/docs/src/inner_layer.md @@ -19,8 +19,8 @@ concrete models: the **GGJ (Glasser–Greene–Johnson)** layer documented below interchangeable solver backends, and the pressureless **SLAYER** Fitzpatrick Riccati layer. Further inner-layer models (kinetic layers) plug in through the same interface. -Two source papers define the equations and the asymptotic construction, and are -cited by their equation numbers throughout the code and below: +Two papers define the equations and the asymptotic construction; the code and this page cite +them by equation number rather than restating them: - **GWP2016** — A. H. Glasser, Z. R. Wang and J.-K. Park, *Computation of resistive instabilities by matched asymptotic expansions*, Phys. Plasmas @@ -29,87 +29,37 @@ cited by their equation numbers throughout the code and below: convergence studies of the resistive inner region equations*, Phys. Plasmas **27**, 012506 (2020). -## Governing equations - -At a rational surface the layer equations couple three fields — the perturbed -flux ``\Psi`` and two auxiliary layer variables ``\Xi`` and ``\Upsilon`` — as -functions of the scaled distance ``x`` from the surface. In the GWP2016 form -(Eq. 11 ≡ GW2020 Eq. 1) they are - -```math -\begin{aligned} -\Psi'' &= H\,\Upsilon' + Q\,(\Psi - x\,\Xi),\\[2pt] -\Xi'' &= \frac{1}{Q^{2}}\Big[\,Q x^{2}\,\Xi - Q x\,\Psi - (E+F)\,\Upsilon - H\,\Psi'\,\Big],\\[2pt] -\Upsilon''&= \frac{1}{Q}\Big[\,x^{2}\,\Upsilon - x\,\Psi - Q^{2}\big(G(\Xi-\Upsilon) - K(E\Xi + F\Upsilon + H\Psi')\big)\Big], -\end{aligned} -``` - -where ``E, F, G, H, K`` are the flux-surface-averaged equilibrium coefficients -of GWP2016 Eq. (A8) and ``Q`` is the dimensionless growth rate defined below. -These coefficients are collected in [`GGJParameters`](@ref InnerLayer.GGJParameters). - -### Dimensionless scales - -The layer is scaled by the local Lundquist number ``S = \tau_R/\tau_A`` (ratio -of resistive to Alfvén time). The displacement and growth-rate scales are - -```math -X_0 = S^{-1/3}, \qquad Q_0 = X_0/\tau_A \qquad \text{(GWP2016 Eqs. A14–A15)}, -``` - -so a physical growth rate ``\gamma`` maps to the scaled eigenvalue -``Q = \gamma/Q_0`` ([`inner_Q`](@ref InnerLayer.inner_Q)) that appears in the equations above, and -the scaled matching data are returned to physical units by the -``X_0^{-2\sqrt{-D_I}} = S^{\,2\sqrt{-D_I}/3}`` rescaling (together with the -``v_1^{\,2\sqrt{-D_I}}`` linear-scale factor; [`rescale_delta`](@ref InnerLayer.rescale_delta)). - -### Mercier index and matching exponents - -The premise of an inner-layer model is local Mercier stability. The Mercier -interchange index and its resistive counterpart are - -```math -D_I = E + F + H - \tfrac14, \qquad -D_R = E + F + H^2 = D_I + \big(H-\tfrac12\big)^2 \qquad \text{(GWP2016 A9–A10)}, -``` - -([`mercier_di`](@ref InnerLayer.mercier_di), [`mercier_dr`](@ref InnerLayer.mercier_dr)). For ``D_I < 0`` the large-``x`` -solutions are the two power laws ``x^{r_\pm}`` with the Frobenius exponents - -```math -r_\pm = \tfrac32 \pm \sqrt{-D_I}, \qquad p_1 \equiv \sqrt{-D_I} -\qquad \text{(GW2020 Eq. 49)}. -``` - -The matching datum ``\Delta`` is the amplitude of the large solution -``x^{r_+}`` when the small solution ``x^{r_-}`` is normalized to unity (i.e. the -ratio of large to small coefficient), in the physical (outer-matching) -normalization. Imposing the two parities at ``x=0`` gives the pair -``(\Delta_+, \Delta_-)`` of GWP2016 Eqs. (34)–(35). Parity is that of the -displacement ``\Xi`` (GWP2016 Eq. 34; Pletzer, Bondeson & Dewar, J. Comput. Phys. **115**, 530 (1994), Eqs. 32–33): -``\Delta_+`` is even, ``\Psi(0)=\Xi'(0)=\Upsilon'(0)=0``, the **interchange** -channel; ``\Delta_-`` is odd, ``\Psi'(0)=\Xi(0)=\Upsilon(0)=0``, the **tearing** -channel, whose flux ``\Psi`` is even and reconnects at the surface. Positional -pairs, such as `deltar` in the matching and `RaySolveResult.Δ`, are always ordered -``(\Delta_+, \Delta_-)``, as in GWP2016 Eq. (38); `InnerLayerResponse` names them -`interchange` and `tearing`. +## Equations and matching data + +The GGJ layer equations (GWP2016 Eq. 11 ≡ GW2020 Eq. 1) couple the perturbed flux ``\Psi`` and +the layer variables ``\Xi``, ``\Upsilon`` in the scaled distance ``x`` from the rational surface. +Their equilibrium coefficients ``E, F, G, H, K`` (GWP2016 Eq. A8) are held in +[`GGJParameters`](@ref InnerLayer.GGJParameters). A physical growth rate ``\gamma`` maps to the +scaled ``Q`` by [`inner_Q`](@ref InnerLayer.inner_Q) (GWP2016 Eqs. A14–A15), and +[`rescale_delta`](@ref InnerLayer.rescale_delta) returns the matching data to physical units. The +model requires Mercier stability, ``D_I < 0`` ([`mercier_di`](@ref InnerLayer.mercier_di), +GWP2016 Eq. A9), so that at large ``x`` the solutions include two power laws (GW2020 Eq. 49). + +The matching datum ``\Delta`` is the ratio of the large to the small power-law coefficient. +Imposing the two parities at ``x = 0`` gives the pair ``(\Delta_+, \Delta_-)`` of GWP2016 +Eqs. (34)–(35). Parity is that of the displacement ``\Xi`` (GWP2016 Eq. 34; Pletzer, Bondeson & +Dewar, J. Comput. Phys. **115**, 530 (1994), Eqs. 32–33): ``\Delta_+`` is even, +``\Psi(0)=\Xi'(0)=\Upsilon'(0)=0``, the **interchange** channel; ``\Delta_-`` is odd, +``\Psi'(0)=\Xi(0)=\Upsilon(0)=0``, the **tearing** channel. Positional pairs, such as `deltar` in +the matching and `RaySolveResult.Δ`, are always ordered ``(\Delta_+, \Delta_-)``, as in GWP2016 +Eq. (38); `InnerLayerResponse` names them `interchange` and `tearing`. ## Numerical method !!! note "Benchmark surface used in the figures" - Every figure on this page is computed on the ``q = 4`` rational-surface - benchmark ([`q4_surface_benchmark`](@ref InnerLayer.q4_surface_benchmark)) — - a fixed set of GGJ layer coefficients (``S = \tau_R/\tau_A \approx 4.6\times10^{6}``, - ``D_I \approx -0.31``) frozen into code from the ``q = 4`` rational surface of - the DIII-D-like (TkMkr H-mode) equilibrium of the `resistive_resmets` - benchmark, at that case's per-surface ``\eta`` and ``\rho``. The well-conditioned - real-``Q`` cross-check in the Validation section instead uses the - Glasser & Wang (2020) Eq. (55) surface. + The figures use the ``q = 4`` surface of the DIII-D-like `resistive_resmets` benchmark, + frozen into [`q4_surface_benchmark`](@ref InnerLayer.q4_surface_benchmark) + (``S \approx 4.6\times10^{6}``, ``D_I \approx -0.31``). ### Solver backends The `GGJ` model exposes three solvers through the `solver` type parameter of -[`GGJModel`](@ref InnerLayer.GGJModel); all consume the same large-``x`` asymptotic basis and return +[`GGJModel`](@ref InnerLayer.GGJModel); all use the same large-``x`` asymptotic basis and return ``\Delta`` in the same convention: | backend | method | robust regime | @@ -118,121 +68,67 @@ The `GGJ` model exposes three solvers through the `solver` type parameter of | `:galerkin` | Hermite-cubic finite-element (real axis) | drift onset ``\lvert Q\rvert \sim 1``; 1% error by ``\lvert Q\rvert \sim 4`` | | `:ray` (default) | rotated contour: inward-marched far-field condition + Hermite-cubic BVP | ``\lvert Q\rvert \sim 500`` on/near the imaginary axis | -The difficulty is the large-``|Q|`` imaginary-``Q`` axis itself, where rotation -and resistivity scans live: there the layer's pseudo-resonance at -``x^2 = -Q^2(G+KF)`` sits directly on the real-``x`` integration path and the -exponential dichotomy weakens, so both older backends degrade — `:shooting` -through the dichotomy of the backward shoot, `:galerkin` through real-axis -oscillation and the on-axis pseudo-resonance. (The poles of ``\Delta(Q)`` -itself lie on and near the **real**-``Q`` axis — they are the layer -eigenvalues; ``\Delta`` is smooth along the imaginary axis.) Measured against -the `:ray` reference along the imaginary axis, `:shooting` holds to -``|Q|\sim 1`` and `:galerkin` to ``|Q|\sim 4`` (the 1% error crossings) -before both lose all accuracy: +Rotation and resistivity scans live on the imaginary-``Q`` axis, where the pseudo-resonance at +``x^2 = -Q^2(G+KF)`` sits on the real-``x`` path. There `:shooting` and `:galerkin` lose +accuracy beyond ``|Q| \sim 1`` and ``|Q| \sim 4`` respectively (the poles of ``\Delta(Q)`` +themselves lie near the real-``Q`` axis): ![Relative error of the :shooting and :galerkin backends against the :ray reference along the imaginary-Q axis, on the q=4 benchmark surface. Each curve's crossing of the 1% line marks that method's practical reach.](figures/inner_layer/backend_regime_map.png) -The `:ray` backend was written to reach the large-``|Q|`` imaginary-axis regime -(rotation and resistivity scans) where these fail. The remainder of this section -describes it. - -### Entire-solution formulation - -`:ray` works with the **plain** state ``v = (\Psi, \Xi, \Upsilon, \Psi', -\Xi', \Upsilon')`` and writes the layer equations as the first-order system - -```math -\frac{dv}{dx} = M(x)\,v . -``` - -The coefficient matrix (the `GGJ` internal `ode_matrix`) is **polynomial** in ``x``, so -``x = 0`` is an ordinary point — the ``x^{-2}/x^{-4}`` singularities of the -GW2020 Eq. (2) scaled form ``(x\Psi,\ \Psi'/x,\ \dots)`` are artifacts of that -scaling, not of the equations. Because the coefficients are entire, the system -continues analytically to complex ``x``, which is what makes the contour -rotation below legitimate. - ### The rotated ray -The equations are continued onto the ray +`:ray` writes the layer equations as ``dv/dx = M(x)\,v`` in the plain state +``v = (\Psi, \Xi, \Upsilon, \Psi', \Xi', \Upsilon')``. ``M`` is polynomial in ``x``, so +``x = 0`` is an ordinary point and the system continues analytically onto the ray ```math -x = e^{i\theta}\, s, \qquad s \in [0, S], \qquad \theta = \tfrac14\arg Q, +x = e^{i\theta}\, s, \qquad s \in [0, S], \qquad \theta = \tfrac14\arg Q . ``` -The angle ``\theta = \tfrac14\arg Q`` makes the parabolic-cylinder exponent of -the outer solutions exactly real and clears the pseudo-resonance at -``x^2 = -Q^2(G + K F)``, which on the imaginary-``Q`` axis is real and large and -therefore sits directly on the un-rotated (real-``x``) contour. Rotating the -contour lifts it off that point; ``\theta = 0`` recovers a real-axis solve. +This angle makes the parabolic-cylinder exponent of the outer solutions real and lifts the +pseudo-resonance off the contour; ``\theta = 0`` is a real-axis solve. ![The rotated integration ray in the complex layer-coordinate plane at Q = 500i. The real-axis contour runs through the pseudo-resonance x² = −Q²(G+KF); the ray at θ = arg(Q)/4 = 22.5° clears it.](figures/inner_layer/rotated_ray_contour.png) ### Hermite-Galerkin BVP -On ``[0, s_m]`` the system is solved with the same Hermite-cubic Galerkin assembly -as the `:galerkin` backend (GWP2016 Eq. 32), written on the ray -(``A u_{ss} + e^{i\theta}B u_s + e^{2i\theta}C u = 0``), with the stock parity -conditions at the ordinary-point origin ``s = 0``. Instead of resonant and extension -cells, the far end carries the point condition +On ``[0, s_m]`` the system is solved with the `:galerkin` backend's Hermite-cubic assembly +(GWP2016 Eq. 32) written on the ray, ``A u_{ss} + e^{i\theta}B u_s + e^{2i\theta}C u = 0``, +with the parity conditions at ``s = 0``. Instead of resonant and extension cells, the far end +carries the point condition ```math v(s_m) = U_s + \Delta\, U_b + c_1 E_1 + c_2 E_2 , ``` -with the matching datum ``\Delta`` and the two decaying-mode amplitudes -``c_1, c_2`` replacing the last node's six Hermite unknowns. Here ``U_s, U_b`` are the -small and large power-like solutions and ``E_{1,2}`` the forward-decaying exponential -pair, all transported from the series radius by the march below. No quantity is ever -propagated across the layer, so the exponential dichotomy that limits the shooting -backend never enters; the boundary condition splits it exactly. The grid resolves the -full local WKB rate in every cell, with a minimum cell count for small ``|Q|`` -(the `GGJ` internal `ray_breaks`). +where ``U_s, U_b`` are the small and large power-like solutions and ``E_{1,2}`` the +forward-decaying exponential pair; ``\Delta, c_1, c_2`` replace the last node's six unknowns. +Each cell resolves the local WKB rate, with a minimum cell count for small ``|Q|``. ### Far-field boundary and the inward march -The large-``x`` boundary data use the **same** `inps` Wasow asymptotic basis as -the other backends (GW2020 Eqs. 3–52), evaluated at complex ``x`` and applied at -the series radius ``S`` where the series is -trusted (residual below tolerance; [`pick_smax`](@ref InnerLayer.pick_smax)). For large ``|Q|`` the -trusted radius ``S`` can be far outside the BVP domain ``s_m``, so the -power-pair data are transported inward from ``S`` to ``s_m`` by an **L-stable -2-stage Radau IIA march** in the quotient modulo the decaying exponential pair — -the subspace in which ``\Delta`` is defined (the `GGJ` internal -`march_boundary`). An implicit method is essential: the decaying pair -grows under backward integration, so any explicit marcher is stability-limited -to ``O(\rho S^2)`` steps. The Radau IIA stability function decays as ``2/z`` at -large ``|z|``, so steps that leave the exponential directions unresolved *damp* -them instead of amplifying them, while the slowly varying power pair stays fully -resolved; ``\Delta`` does not depend on the decaying-pair content. Damped steps are -only taken where every growing mode has ``z > 8``, clear of the method's -amplifying window ``0 < z < 6``; nearer ``s_m`` the march resolves the growing -directions and periodically projects out the decaying content. - -The march decides where to switch to resolved steps from the local rates. On the -real axis with imaginary ``Q`` the pseudo-resonance is a turning point where one -rate vanishes, the switch lands on it, and the decaying directions cannot be -identified there; the default ``\theta = \arg(Q)/4`` keeps it off the contour. - -The damped-zone march runs in `Complex{Double64}` extended precision. At large -``S`` the near-parallel power-pair geometry amplifies the structured backward -error of the ill-conditioned implicit solves into ``\Delta``-mixing of order -``10^{-4}`` at ``|Q| = 500`` in `Float64`; extended precision removes this -floor, while the well-conditioned resolved band stays in `Float64`. - -The result is a seamless numeric↔asymptotic solution: the BVP solution -on ``[0, s_m]`` and the analytic ``u_\mathrm{small} + \Delta\,u_\mathrm{big}`` -representation for ``s \ge S`` share the same power-law tail — the overlap the -outer-region matching relies on. +The boundary data come from the same `inps` Wasow basis as the other backends (GW2020 +Eqs. 3–52), evaluated at the radius ``S`` where its residual is below tolerance +([`pick_smax`](@ref InnerLayer.pick_smax)). At large ``|Q|``, ``S`` lies far beyond ``s_m``, and +the power pair is marched inward by 2-stage Radau IIA modulo the decaying pair, the subspace in +which ``\Delta`` is defined. The decaying pair grows under backward integration, so an explicit +method would need ``O(\rho S^2)`` steps. Radau's stability function decays as ``2/z``, so steps +with every growing mode at ``z > 8`` damp those directions while the slowly varying power pair +stays resolved. Nearer ``s_m`` the march resolves the growing directions, carries the decaying +frame, and projects it out periodically. The damped zone runs in `Complex{Double64}`: in +`Float64` the ill-conditioned implicit solves mix the power pair at about ``10^{-4}`` at +``|Q| = 500``. + +On the real axis with imaginary ``Q`` the switch to resolved steps lands on the +pseudo-resonance, a turning point where the decaying directions cannot be identified; the +default ``\theta = \arg(Q)/4`` keeps it off the contour. For matching, `solve_inner_profile` returns ``\Delta`` and the layer-center fields -``\Psi(0), \Xi(0)`` from the single rotated solve; ``x = 0`` lies on every contour, -so these are the real-axis values and the penetrated field needs nothing more. -Fields across the layer on the real ``\psi`` axis are opt-in -(`GGJModel(; real_profiles=true)`): they come from an extra ``\theta = 0`` solve, -whose ``\Delta`` is compared against the rotated one (`certΔ`, warned when they -disagree). At large ``|Q|`` near the imaginary axis that real-axis solve can fail -for the turning-point reason above, and the warning says so. +``\Psi(0), \Xi(0)`` from the rotated solve; ``x = 0`` lies on every contour, so these are the +real-axis values. Fields across the layer on the real ``\psi`` axis are opt-in +(`GGJModel(; real_profiles=true)`): they come from an extra ``\theta = 0`` solve, whose ``\Delta`` +is checked against the rotated one (`certΔ`, which warns on disagreement, as can happen at large +``|Q|`` near the imaginary axis). ![Inner-layer fields Ψ, Ξ, Υ on the rotated ray for the q=4 surface at Q = 2i. The BVP solution (solid) joins the asymptotic representation (dashed) seamlessly at the match point S = s_m.](figures/inner_layer/solution_profiles.png) @@ -247,12 +143,8 @@ reproduces the Fortran `rmatch deltac` solver to ``\sim 10^{-8}``: | ``\Delta_+`` (interchange) | ``3.698368\times 10^{4}`` | ``3.69789\times 10^{4}`` | | ``\Delta_-`` (tearing) | ``14.759721`` | ``14.759715`` | -The large ``\lvert\Delta_+\rvert \sim 4\times10^{4}`` means this -operating point sits near a pole of ``\Delta(Q)``, where every solver's error -is amplified by the pole geometry; the ``1.3\times10^{-4}`` -`:galerkin`↔`:ray` difference in ``\Delta_+`` (versus -``4\times10^{-7}`` in ``\Delta_-``) is consistent with that -amplification, not a defect of either backend. +This point sits near a pole of ``\Delta_+(Q)``, which amplifies every solver's error; hence the +``1.3\times10^{-4}`` `:galerkin`↔`:ray` difference in ``\Delta_+`` against ``4\times10^{-7}`` in ``\Delta_-``. **Physical benchmark on the imaginary axis.** On the ``q=4`` rational-surface benchmark ([`q4_surface_benchmark`](@ref InnerLayer.q4_surface_benchmark), ``S \approx 4.58\times10^6``, @@ -264,15 +156,12 @@ entirely beyond `:galerkin`: | ``\Delta_+`` (interchange) | ``2.4720 + 13.3540\,i`` | | ``\Delta_-`` (tearing) | ``0.13750 + 0.74275\,i`` | -**Convergence and contour invariance.** Because ``\Delta`` is an analytic -invariant of the contour angle, re-solving with each numerical knob perturbed on -an independent axis ([`delta_convergence`](@ref InnerLayer.delta_convergence)) gives an honest error bar: at -``Q = 500i`` the worst-case spread across all knobs is ``\sim 5\times10^{-6}`` -for ``\Delta_+`` and ``\sim 6\times10^{-7}`` for -``\Delta_-``. That is a single-machine error bar: across -machines/BLAS builds the absolute values reproduce to ``\sim 10^{-5}`` -relative (the damped-zone implicit solves carry platform-dependent structured -roundoff), which is why the table above quotes five significant figures. +**Convergence and contour invariance.** ``\Delta`` does not depend on the contour angle, so +re-solving with each numerical knob perturbed in turn +([`delta_convergence`](@ref InnerLayer.delta_convergence)) gives an error bar: at ``Q = 500i`` the +worst case is ``\sim 5\times10^{-6}`` for ``\Delta_+`` and ``\sim 6\times10^{-7}`` for ``\Delta_-``. +Across machines and BLAS builds the values reproduce to ``\sim 10^{-5}`` relative, hence the five +significant figures above. ![Relative change of Δ at Q = 500i under independent perturbations of each numerical knob (contour angle, mesh resolution, series order/radius, march tolerance, handoff radius, purification depth). The worst-case spread is the reported error bar.](figures/inner_layer/convergence_Sinvariance.png) diff --git a/src/InnerLayer/GGJ/Galerkin.jl b/src/InnerLayer/GGJ/Galerkin.jl index 88df54feb..a5bae0c39 100644 --- a/src/InnerLayer/GGJ/Galerkin.jl +++ b/src/InnerLayer/GGJ/Galerkin.jl @@ -1,60 +1,21 @@ # Galerkin.jl # -# Hermite-cubic finite element (Galerkin) solver for the GGJ inner-layer -# model, in the "resonant + noexp + inps" configuration. The half-domain -# problem (x ∈ [0, xmax]) is solved with parity boundary conditions at -# x = 0 and asymptotic matching at x = xmax. -# -# The solved field is the 3-component inner-layer solution u = (Ψ, Ξ, Υ) -# obeying the GGJ inner-region equations -# GWP2016 Eq. (11) ≡ GW2020 Eq. (1): -# -# Ψ_xx − H Υ_x − Q(Ψ − x Ξ) = 0, -# Q² Ξ_xx − Q x² Ξ + Q x Ψ + (E + F) Υ + H Ψ_x = 0, -# Q Υ_xx − x² Υ + x Ψ + Q²[G(Ξ − Υ) − K(E Ξ + F Υ + H Ψ_x)] = 0, -# -# recast in matrix form A Ψ'' + B Ψ' + C Ψ = 0 (GWP2016 Eqs. 12–15) and -# assembled here in the weak-form coefficient layout `I·u'' − V·u' − U·u = 0` -# with (I, V, U) = (A, −B, −C). See `_physical_uv` for the row-by-row map. -# -# This module ports the GWP2016 inner-region singular-Galerkin method (Sec. III): -# the half-domain weak form (Eq. 32) on a packed Hermite-cubic grid (Eq. 33), -# with resonant/extension cells (Fig. 1) supplying the matching data (Eqs. 34–35). -# -# Configuration assumed: -# gal_method = "resonant" method = true noexp = true -# basis_type = 0 (Hermite) fulldomain = 0 inps_type = "inps" -# mpert = 3 (Ψ, Ξ, Υ) np = 3 (Hermite cubic → 4 DOFs/node) -# -# References: GWP2016 (Phys. Plasmas 23, 112506) for the Galerkin method and -# matching; GW2020 (Phys. Plasmas 27, 012506) for the large-x asymptotic basis. +# Hermite-cubic finite-element (Galerkin) solver for the GGJ inner layer, porting the GWP2016 +# Sec. III singular-Galerkin method: the half-domain weak form (Eq. 32) on a packed grid +# (Eq. 33), parity conditions at x = 0, and resonant/extension cells at x_max supplying the +# matching data (Eqs. 34–35). Fortran deltac configuration: "resonant" + noexp + inps, +# Hermite basis, mpert = 3 (Ψ, Ξ, Υ). The equations are assembled as I·u'' − V·u' − U·u = 0 +# with (I, V, U) = (A, −B, −C) of GWP2016 Eq. 12; see `_physical_uv`. using LinearAlgebra using FastGaussQuadrature: gausslobatto using QuadGK: quadgk -# ----------------------------------------------------------------------- -# Physical-variable helpers. -# ----------------------------------------------------------------------- - """ -Build the (I, U, V) coefficient matrices of the second-order system -`I·u'' − V·u' − U·u = 0` for u = (Ψ, Ξ, Υ) at coordinate `x`. -All matrices are 3×3 complex. - -These are the matrices A, B, C of GWP2016 Eq. (12), `A Ψ'' + B Ψ' + C Ψ = 0`, -with A given in Eq. (14), B in Eq. (14), and C in Eq. (15). The code's weak-form -layout flips the off-diagonal signs: (I, V, U) = (A, −B, −C). - -Each matrix row is one GGJ inner-region equation (GWP2016 Eq. 11 ≡ GW2020 Eq. 1); -reading `I u'' − V u' − U u` across a row reproduces the corresponding equation: - -row 1 (Ψ): Ψ_xx − H Υ_x − Q(Ψ − x Ξ) = 0 -⇒ I=(1,0,0) V=(0,0,H) U=(Q, −Qx, 0) -row 2 (Ξ): Q² Ξ_xx − Q x² Ξ + Q x Ψ + (E+F) Υ + H Ψ_x = 0 -⇒ I=(0,Q²,0) V=(−H,0,0) U=(−Qx, Q x², −(E+F)) -row 3 (Υ): Q Υ_xx − x² Υ + x Ψ + Q²[G(Ξ−Υ) − K(E Ξ + F Υ + H Ψ_x)] = 0 -⇒ I=(0,0,Q) V=(K Q² H,0,0) U=(−x, −Q²(G−KE), x²+Q²(G+KF)) + _physical_uv(params, Q, x) -> (I, U, V) + +3×3 coefficients of `I·u'' − V·u' − U·u = 0` for u = (Ψ, Ξ, Υ) at real or complex `x`, with +(I, V, U) = (A, −B, −C) of GWP2016 Eqs. 12–15; each row is one equation of GWP2016 Eq. 11. """ function _physical_uv(params::GGJParameters, Q::ComplexF64, x::Number) e = ComplexF64(params.E) @@ -66,26 +27,15 @@ function _physical_uv(params::GGJParameters, Q::ComplexF64, x::Number) q2 = q * q x2 = x * x - # I = A of GWP2016 Eq. (14): diag(1, Q², Q), coefficients of (Ψ_xx, Ξ_xx, Υ_xx). Imat = @SMatrix ComplexF64[1 0 0; 0 q2 0; 0 0 q] - # U = −C of GWP2016 Eq. (15): coefficients of −u in each equation - # (stored pre-scaled: row 2 ×Q², row 3 ×Q, matching - # the I-row normalization). - # row 1 (Ψ): (Q, −Q x, 0) - # row 2 (Ξ): (−Q x, Q x², −(E+F)) - # row 3 (Υ): (−x, −Q²(G−KE), x²+Q²(G+KF)) + # U = −C (GWP2016 Eq. 15) and V = −B (Eq. 14), rows pre-scaled as in the Fortran. #! format: off U = @SMatrix ComplexF64[ q (-q * x) 0 (-x / q) * q2 (x2 / q) * q2 (-(e + f) / q2) * q2 (-x / q) * q (-(g - k * e) * q) * q (x2 / q + (g + k * f) * q) * q ] - - # V = −B of GWP2016 Eq. (14): coefficients of −u' in each equation (same row scaling as U): - # row 1 (Ψ): (0, 0, H) ⇒ −H Υ_x - # row 2 (Ξ): (−H, 0, 0) ⇒ +H Ψ_x - # row 3 (Υ): (K Q² H, 0, 0) ⇒ −K Q² H Ψ_x V = @SMatrix ComplexF64[ 0 0 h (-h / q2) * q2 0 0 @@ -96,12 +46,7 @@ function _physical_uv(params::GGJParameters, Q::ComplexF64, x::Number) return Imat, U, V end -# ----------------------------------------------------------------------- -# Hermite cubic basis functions. -# Returns (pb[1:4], qb[1:4]) where pb = values, qb = derivatives, -# indexed 1:4 → physical 0:3. -# ----------------------------------------------------------------------- - +# Hermite cubic basis on [x0, x1]: values pb and derivatives qb, slots 1:4 ↔ (u₀, u₀', u₁, u₁'). function _hermite(x::Real, x0::Real, x1::Real) dx = x1 - x0 t0 = (x - x0) / dx @@ -123,14 +68,8 @@ function _hermite(x::Real, x0::Real, x1::Real) return pb, qb end -# ----------------------------------------------------------------------- -# Grid packing. The pfac > 1 branch is the GWP2016 -# inner-region packing X(ξ,λ) = ln[(1+λξ)/(1−λξ)] / ln[(1+λ)/(1−λ)] -# (Eq. 33), which concentrates nodes near X = 0; pfac = 1 gives a uniform -# grid, and pfac in (0,1) the complementary edge-packed map. The grid-density -# ratio is P(λ) = 1 − λ² (GWP2016 between Eqs. 5 and 33). -# ----------------------------------------------------------------------- - +# Grid packing (GWP2016 Eq. 33): pfac > 1 concentrates nodes near X = 0, pfac = 1 is uniform, +# 0 < pfac < 1 packs toward the edge. function _pack(nx::Int, pfac::Float64, side::String) xi = zeros(Float64, 2nx + 1) if side == "right" @@ -169,24 +108,14 @@ function _pack(nx::Int, pfac::Float64, side::String) return x end -# ----------------------------------------------------------------------- -# Three-level xmax sweep. The cutoff -# x_max is the position where the asymptotic-basis residual Δ (GW2020 Eq. 54, -# computed by `asymptotic_residual`) drops below a target tolerance — the -# choice studied in GW2020 Sec. III and Fig. 3, where x_max is taken where the -# error falls to ~1e−7. Three tolerance levels set x_max and the two thin -# matching cells (dx1, dx2) just inside it. -# Returns (xmax, dx1, dx2, cache). -# ----------------------------------------------------------------------- - +# x_max and the two thin matching cells inside it, from where the series residual (GW2020 Eq. 54) +# crosses three tolerances. Returns (xmax, dx1, dx2, cache). function _xmax_3level(params::GGJParameters, Q::ComplexF64; kmax::Int=8, xfac::Float64=1.0, eps_vec::NTuple{3,Float64}=(1e-2, 5e-7, 1e-7)) cache = build_asymptotics(params, Q; kmax=kmax) - # Bisection-based root finder: find the exact x where max(residual) = eps, - # for each of the 3 tolerance levels. First do a coarse sweep to bracket, - # then bisect to machine precision. + # Bracket each crossing on a coarse log sweep, then bisect. dxfac = 10.0^0.01 xmax_vals = zeros(Float64, 3) brackets = Vector{Tuple{Float64,Float64}}(undef, 3) @@ -233,17 +162,10 @@ function _xmax_3level(params::GGJParameters, Q::ComplexF64; return (; xmax, dx1, dx2, cache) end -# ----------------------------------------------------------------------- -# Cell types and grid construction. These are the grid cells of GWP2016 -# Fig. 1, laid out moving toward the cutoff x_max: ordinary "normal" cells -# (CT_NONE) carrying 4 Hermite-cubic DOFs/node, "extension" cells (CT_EXT2, -# CT_EXT1, CT_EXT) where the small resonant power series is blended into the -# Hermite basis, and the "resonant" cell (CT_RES) at x_max holding the large -# resonant solution whose coefficient provides the matching data (Eqs. 34–35). -# Here the half-domain has a single resonant cell at x_max (the X = 0 end is -# the parity boundary, not a singular surface). -# ----------------------------------------------------------------------- - +# Cell types of GWP2016 Fig. 1, toward x_max: normal Hermite cells (CT_NONE), extension cells +# blending the small resonant solution into the Hermite basis (CT_EXT2, CT_EXT1, CT_EXT), and the +# resonant cell (CT_RES) whose large-solution coefficient is the matching data. The half domain has +# one resonant cell; x = 0 carries the parity conditions. @enum CellType CT_NONE CT_EXT2 CT_EXT1 CT_EXT CT_RES struct GalerkinCell @@ -264,9 +186,7 @@ struct GalerkinWorkspace mat::Array{ComplexF64,3} # (ldab, ndim, 2) banded storage rhs::Matrix{ComplexF64} # (ndim, 2) sol::Matrix{ComplexF64} # (ndim, 2) - # Reusable scratch buffers, zeroed per-cell via `fill!`. Eliminates the - # per-cell `zeros(...)` that otherwise allocates thousands of MiB over a - # full dispersion scan. + # Per-cell scratch buffers, zeroed with `fill!`. cell_mat_buf::Array{ComplexF64,4} # (mpert=3, mpert, np+1=4, np+1=4) cell_mat_ext_buf::Array{ComplexF64,4} # (3, 3, 4, 4) max over CT_EXT/EXT1/EXT2 cell_rhs_ext_buf::Matrix{ComplexF64} # (3, 4) @@ -390,9 +310,7 @@ function _galerkin_workspace(x_nodes::Vector{Float64}, etypes::Vector{CellType}) mat = zeros(ComplexF64, ldab, ndim, 2) rhs = zeros(ComplexF64, ndim, 2) sol = zeros(ComplexF64, ndim, 2) - # Preallocate per-cell scratch buffers sized to the max case (np+1=4). - # Smaller cells (e.g. CT_EXT with cell.np=1) use a (2×2) sub-slice and - # rely on fill!(buf, 0) to keep the remainder zero. + # Scratch buffers sized for np + 1 = 4; smaller cells use a zeroed sub-slice. cell_mat_buf = zeros(ComplexF64, mpert, mpert, np + 1, np + 1) cell_mat_ext_buf = zeros(ComplexF64, mpert, mpert, np + 1, np + 1) cell_rhs_ext_buf = zeros(ComplexF64, mpert, np + 1) @@ -404,16 +322,8 @@ function _galerkin_workspace(x_nodes::Vector{Float64}, etypes::Vector{CellType}) ab_buf, rhs_buf) end -# ----------------------------------------------------------------------- -# Local assembly: Gauss quadrature for "none" cells. -# Evaluates the GWP2016 Eq. (32) bilinear form on one cell. After integrating -# the A-term by parts, the symmetric weak form is -# Σⱼ [−(αᵢ', A αⱼ') + (αᵢ, B αⱼ') + (αᵢ, C αⱼ)] uⱼ , -# which in this code's (I, V, U) = (A, −B, −C) convention is assembled below as -# I·(αᵢ' αⱼ') + V·(αᵢ αⱼ') + U·(αᵢ αⱼ) with αᵢ the Hermite-cubic basis -# (pb = values, qb = derivatives). Scalar products use Gauss–Lobatto quadrature. -# ----------------------------------------------------------------------- - +# One cell's GWP2016 Eq. 32 bilinear form after integrating the A-term by parts, +# I·(αᵢ' αⱼ') + V·(αᵢ αⱼ') + U·(αᵢ αⱼ), by Gauss–Lobatto quadrature. function _gauss_quad!(cell_mat::Array{ComplexF64,4}, cell::GalerkinCell, quad_nodes::Vector{Float64}, quad_weights::Vector{Float64}, params::GGJParameters, Q::ComplexF64; θ::Float64=0.0) @@ -449,15 +359,8 @@ function _gauss_quad!(cell_mat::Array{ComplexF64,4}, cell::GalerkinCell, end end -# ----------------------------------------------------------------------- -# Extension assembly. Handles ext, ext1, ext2 cell -# types: the GWP2016 extension cells (Fig. 1) where the small resonant power -# series (column 2 of the asymptotic basis) drives the response and the large -# resonant solution (column 1) is blended into the Hermite cubics with -# C¹ continuity. This couples the bulk Hermite DOFs to the asymptotic emap DOF -# via the same Eq. (32) bilinear form; the small-solution terms form the RHS. -# ----------------------------------------------------------------------- - +# Extension cells (GWP2016 Fig. 1): the large resonant solution (column 1) is blended into the +# Hermite cubics with C¹ continuity as an extra DOF; the small one (column 2) drives the RHS. function _extension!(cell_mat::Array{ComplexF64,4}, cell_rhs::Matrix{ComplexF64}, cell::GalerkinCell, quad_nodes::Vector{Float64}, quad_weights::Vector{Float64}, @@ -544,26 +447,14 @@ function _extension!(cell_mat::Array{ComplexF64,4}, cell_rhs::Matrix{ComplexF64} end end -# ----------------------------------------------------------------------- -# Resonant integral, evaluated with QuadGK. Evaluates the -# GWP2016 Eq. (32) bilinear form over the resonant cell using the asymptotic -# (power-series) solutions as both test and trial functions — the scalar -# products that GWP2016 notes "are non-analytic and therefore require an -# adaptive integration" rather than Gauss quadrature. -# Computes ∫_{x_left}^{x_lsode} ua_1^T L ua_j dx for j=1 and j=2. -# With noexp, only (1,1) and (1,2) entries of the 1×2 result matter -# (ip=1 only for test function, jp=1 for stiffness, jp=2 for RHS). -# ----------------------------------------------------------------------- - +# Resonant-cell scalar products ∫ ua₁ᵀ L ua_j dx (j = 1 stiffness, j = 2 RHS) with the asymptotic +# solutions as test and trial functions; non-analytic, so adaptive QuadGK (GWP2016 Sec. III). function _resonant_integral(cell::GalerkinCell, params::GGJParameters, Q::ComplexF64, cache::InnerAsymptoticsCache; tol::Float64=1e-5) x_left = cell.x_left x_right = cell.x_lsode - # u_res[1,1] = ∫ ua_1^T L ua_1 dx (stiffness) - # u_res[1,2] = ∫ ua_1^T L ua_2 dx (RHS/driving) - # Weak form after IBP: (test') I (trial') + (test) V (trial') + (test) U (trial) function integrand_11(x) ua, dua = physical_ua_dua(cache, x) Imat, Umat, Vmat = _physical_uv(params, Q, x) @@ -604,8 +495,6 @@ function _assemble_and_solve!(ws::GalerkinWorkspace, fill!(ws.mat, 0) fill!(ws.rhs, 0) - # Per-cell assembly — reuse the preallocated scratch buffers, zeroing - # only the sub-slice actually used by this cell's np_eff. cell_mat = ws.cell_mat_buf cell_mat_ext = ws.cell_mat_ext_buf cell_rhs_ext = ws.cell_rhs_ext_buf @@ -622,11 +511,7 @@ function _assemble_and_solve!(ws::GalerkinWorkspace, # Extension terms if cell.etype in (CT_EXT, CT_EXT1, CT_EXT2) - # np_eff matches the semantic size: CT_EXT has cell.np=1 → ext slot - # at index cell.np+1=2 (using 0-based; +1 in Julia), so the array - # used by the current code is (3,3,cell.np+2,cell.np+2)=(3,3,3,3). - # For CT_EXT1/EXT2 it's (3,3,cell.np+1,cell.np+1)=(3,3,4,4). - # Either way npp = cell.etype == CT_EXT ? cell.np + 1 : cell.np. + # CT_EXT carries one extra (asymptotic) slot after its Hermite pair. np_eff = cell.etype == CT_EXT ? cell.np + 1 : cell.np fill!(cell_mat_ext, 0) fill!(cell_rhs_ext, 0) @@ -669,9 +554,7 @@ function _assemble_and_solve!(ws::GalerkinWorkspace, end end - # Surface term at xmax for "resonant" method: the boundary contribution - # [αᵢ A uⱼ']_{x_max} from the IBP of the A-term in GWP2016 Eq. (32), kept - # here (not dropped) because the resonant cell carries the matching data. + # IBP surface term [αᵢ A uⱼ'] at x_max (GWP2016 Eq. 32), kept because the resonant cell carries Δ. res_cell = ws.cells[ws.nx] x_lsode = res_cell.x_lsode ua_xmax, dua_xmax = physical_ua_dua(cache, x_lsode) @@ -732,12 +615,8 @@ function _parity_bcs_and_solve!(ws::GalerkinWorkspace, params::GGJParameters, Q: end end - # Apply parity BCs for each solution. The inner equations have reflection symmetry - # about X=0 (GWP2016 Sec. III); parity is that of the displacement Ξ (GWP2016 Eq. 34): - # isol=1 is even (+, interchange: even Ξ, Υ, odd Ψ), isol=2 odd (−, tearing: odd Ξ, Υ, - # even Ψ). Each contributes a Δ± for outer-region matching (GWP2016 Eqs. 34–35). - # For each isol, build a modified local - # matrix for ip=0..1 of cell 1, then write it into the global matrix. + # Parity conditions at X = 0 (GWP2016 Sec. III), parity of the displacement Ξ (Eq. 34): + # isol = 1 even (Δ₊, interchange), isol = 2 odd (Δ₋, tearing). The ip = 0 rows are replaced. for isol in 1:2 # Zero out ip=0 rows in the global matrix for ipert in 1:mpert @@ -749,14 +628,7 @@ function _parity_bcs_and_solve!(ws::GalerkinWorkspace, params::GGJParameters, Q: ws.mat[offset+i-jj, jj, isol] = 0 end end - # Even parity (isol=1): Ψ(0)=0, Ξ'(0)=0, Υ'(0)=0 - # → row=Ψ(ip=0), col=Ψ(ip=0): A[map[1,1], map[1,1]] = 1 - # → row=Ξ(ip=0), col=Ξ(ip=1): A[map[2,1], map[2,2]] = 1 - # → row=Υ(ip=0), col=Υ(ip=1): A[map[3,1], map[3,2]] = 1 - # Odd parity (isol=2): Ψ'(0)=0, Ξ(0)=0, Υ(0)=0 - # → row=Ψ(ip=0), col=Ψ(ip=1): A[map[1,1], map[1,2]] = 1 - # → row=Ξ(ip=0), col=Ξ(ip=0): A[map[2,1], map[2,1]] = 1 - # → row=Υ(ip=0), col=Υ(ip=0): A[map[3,1], map[3,1]] = 1 + # Even: Ψ(0) = Ξ'(0) = Υ'(0) = 0; odd: Ψ'(0) = Ξ(0) = Υ(0) = 0 (ip = 1 slots are derivatives). if isol == 1 i = cell1.map[1, 1] j = cell1.map[1, 1] @@ -883,8 +755,7 @@ end # ----------------------------------------------------------------------- function _solution_profile(ws::GalerkinWorkspace; npc::Int=10) mpert = 3 - # Preallocate the output arrays (every qualifying cell contributes npc points) instead of growing - # them with vcat inside the loop, which reallocates and copies the whole array each iteration (O(n²)). + # Every Hermite cell contributes npc points. npts = 0 for cell in ws.cells (cell.etype == CT_RES || cell.etype == CT_EXT) && continue diff --git a/src/InnerLayer/GGJ/Ray.jl b/src/InnerLayer/GGJ/Ray.jl index 7550eb84b..735b760de 100644 --- a/src/InnerLayer/GGJ/Ray.jl +++ b/src/InnerLayer/GGJ/Ray.jl @@ -1,30 +1,12 @@ # Ray.jl # -# Rotated-contour backend (`GGJModel{:ray}`) for the GGJ inner-layer matching data, -# robust at large |Q| where the stock `:galerkin` matching degrades. Method write-up: -# docs/src/inner_layer.md, "Numerical method". -# -# The equations are continued analytically onto the ray x = e^{iθ}s, θ = arg(Q)/4 -# (parabolic-cylinder exponent exactly real; pseudo-resonance off the contour). The -# far-field condition uses the same inps Wasow basis as the other backends, applied at -# the series radius S and transported S → s_m by an L-stable 2-stage Radau IIA march in -# the quotient modulo the decaying exponential pair (damped zone in Complex{Double64}). -# On [0, s_m] the stock Hermite-cubic Galerkin assembly (Galerkin.jl) solves the BVP with -# parity conditions at the origin and v(s_m) = Us + Δ·Ub + c₁E₁ + c₂E₂ at the far end. - -# The GGJ inner-region equations (GWP2016 Eq. 11 ≡ GW2020 Eq. 1) as a plain -# first-order system in v = (Ψ, Ξ, Υ, Ψ', Ξ', Υ'), dv/dx = M(x)·v. -# All coefficients are POLYNOMIAL in x, so x = 0 is an ordinary point (the -# x⁻²/x⁻⁴ singularities of the GW2020 Eq. 2 form are artifacts of the -# (xΨ, Ψ'/x) scaling) and the system continues analytically to complex x. -# -# Ψ'' = H Υ' + Q(Ψ − xΞ) -# Ξ'' = [Q x² Ξ − Q x Ψ − (E+F) Υ − H Ψ'] / Q² -# Υ'' = [x² Υ − x Ψ − Q²(G(Ξ−Υ) − K(EΞ + FΥ + HΨ'))] / Q -# -# Row-by-row this matches the deltac `inpso_get_uv` matrices (I, V, U) after -# dividing each equation by its diagonal second-derivative coefficient -# (1, Q², Q). +# Rotated-contour backend (`GGJModel{:ray}`): the GGJ equations continued onto x = e^{iθ}s, +# θ = arg(Q)/4. Far-field series data at the radius S are marched inward to s_m modulo the +# decaying exponential pair, then the Galerkin.jl Hermite assembly solves [0, s_m] with +# v(s_m) = Us + Δ·Ub + c₁E₁ + c₂E₂. Method and rationale: docs/src/inner_layer.md. + +# GWP2016 Eq. 11 as dv/dx = M(x)·v in the plain state v = (Ψ, Ξ, Υ, Ψ', Ξ', Υ'). M is polynomial +# in x, so x = 0 is an ordinary point and the system continues analytically to complex x. """ ode_matrix([CT,] p::GGJParameters, Q, x) -> SMatrix{6,6,CT} @@ -95,38 +77,11 @@ function ray_breaks(params::GGJParameters, Q::ComplexF64, θ::Float64, S::Float6 return breaks end -# Large-s boundary data at the matching point on the ray x = e^{iθ}s. -# -# The admissible (bounded-as-s→∞) solution space is spanned by -# { u_small, u_big } — the two power-like Mercier solutions, taken from -# the inps series in the standard normalization, and -# { E₁, E₂ } — the two forward-DECAYING exponential solutions. -# -# The inps series is only trusted at radius S (residual ≤ smax_tol), which -# for extreme-coefficient surfaces (K ~ 10⁶) can be S ~ 10⁴–10⁵, while the -# BVP ends at s_m ~ 30–150. The gap is bridged by MARCHING the -# power-pair data W = [u_small, u_big] backward S → s_m. -# -# Marching design (the hard-won part): -# - Backward, the decaying pair GROWS at rate ρs (ρ = Re(e^{2iθ}/√Q)), up -# to ~10³/unit at large s. Any explicit integrator — including -# projected/continuous-QR variants, whose unprojected stage points -# reintroduce the transverse stiffness — is stability-limited to -# h ≲ 3/(ρs), i.e. O(ρS²) steps: hopeless at S ~ 10⁵. -# - The system is LINEAR, so we use an implicit method (2-stage Radau IIA, -# order 3; one 12×12 solve per step) with stability function -# R(z) = 2(3+z)/(z² − 4z + 6) → 2/z as |z| → ∞ in any direction. Resolved -# slow content is integrated to 3rd order; under-resolved exponential -# directions are DAMPED whatever their sign. That is normally an accuracy -# vice; here it is exactly the required behavior, because Δ is defined -# modulo the decaying pair. For a backward-growing mode |R| > 1 on -# 0 < z < 6 (poles at z = 2 ± i√2), so damped steps need z > 8. -# - In the partially-resolved band (|z| = ρs·h ≲ 10) genuine backward -# growth of rounding-injected decaying-pair content still occurs, so W -# is PURGED against the decaying frame every `purge_budget` e-folds of -# ∫g_max ds. Purging only ever removes span{E} content — -# legitimate by the definition of Δ — so the transported coefficients -# of u_small/u_big are exact up to integrator tolerance. +# Far-field boundary data. The admissible solutions at large s are the power pair (u_small, u_big) +# from the inps series and the forward-decaying exponential pair E. The series is trusted only at +# S, which can lie far beyond s_m, so the power pair is marched S → s_m by 2-stage Radau IIA, +# R(z) = 2(3+z)/(z² − 4z + 6). Unresolved steps (z > 8, clear of |R| > 1 on 0 < z < 6) damp the +# exponential directions, which is harmless because Δ is defined modulo E. # Small and large power-like solutions at x as 6-component states (Ψ, Ξ, Υ, Ψ', Ξ', Υ'). function _power_states(cache::InnerAsymptoticsCache, x::Number) @@ -150,13 +105,7 @@ function decaying_pair(params::GGJParameters, Q::ComplexF64, θ::Float64, S::Flo ρ = real(cis(2θ) / sq) ρ > 0 || throw(ArgumentError("θ=$θ gives ρ=$ρ ≤ 0; decaying pair undefined")) ph = cis(θ) - # Purification window: BOTH backward-growing directions must separate - # from the power pair by ≥ `growth` e-folds over [S, S+ΔS], so the - # budget is set by the SLOWEST grower's rate margin over the algebraic - # power rates (from the frozen spectrum) — not by ρS. At moderate |Q| - # the fast-Ohm grower can be ~0.6/unit while ρS ~ 10²: budgeting on ρS - # leaves the second frame column O(1)-contaminated with power content, - # which then poisons every march purge that uses the frame. + # Window ΔS: the slowest backward grower separates from the power pair by `growth` e-folds. g2 = Inf gmax_loc = 0.0 for λ in eigvals(Matrix(ph * ode_matrix(params, Q, ph * S))) @@ -167,11 +116,7 @@ function decaying_pair(params::GGJParameters, Q::ComplexF64, θ::Float64, S::Flo gsep = isfinite(g2) ? max(g2 - 20.0 / S, 0.05 * g2) : ρ * S ΔS = min(growth / gsep, 3.0 * S) - # Step resolution must use the TRUE local spectrum, not the analytic - # ρs + |√Q| estimate: on extreme-coefficient surfaces the Υ-family rate - # √|Q(G+KF)| dominates at small s and the analytic estimate under-counts - # it 10×, leaving h·λ ~ 0.2 — stable but phase-inaccurate, which corrupts - # the extracted frame directions (observed as O(1) θ-drift downstream). + # Resolve the true local spectrum; ρs + |√Q| under-counts the Υ-family rate √|Q(G+KF)|. for λ in eigvals(Matrix(ph * ode_matrix(params, Q, ph * (S + ΔS)))) gmax_loc = max(gmax_loc, abs(real(λ))) end @@ -206,9 +151,7 @@ end Transport the power-pair boundary data from the series radius `S` inward to `s_m` along the ray, modulo the decaying exponential pair (the quotient in -which Δ is defined). 2-stage Radau IIA (L-stable) with Φ-budgeted purges -against a carried decaying frame; explicit marchers cannot do this at large S -(see file header). +which Δ is defined): 2-stage Radau IIA with purges against a carried decaying frame. """ function march_boundary(params::GGJParameters, Q::ComplexF64, θ::Float64, S::Float64, s_m::Float64, Us::Vector{ComplexF64}, Ub::Vector{ComplexF64}; @@ -237,51 +180,22 @@ function march_boundary(params::GGJParameters, Q::ComplexF64, θ::Float64, return W + hc * ((CT(3) / 4) * @view(K[1:6, :]) + (CT(1) / 4) * @view(K[7:12, :])) end - # Extended precision (Double64) for the damped-zone W march. - # At z = ρ·c·s² ≫ 1 the step matrices have cond ~ z and the LU backward - # error has a SYSTEMATIC direction set by the elimination structure — it - # does not dither away, accumulating a relative error Σ eps·z ≈ eps·ρS²/2 - # on the power columns that is INDEPENDENT of the step law (c cancels). - # The near-parallel power-pair geometry at large S turns that into - # u_small/u_big coefficient mixing β ~ eps·ρS²/2 · (‖u_big‖/‖u_small‖)(S) - # ~ 1e-4 at |Q| = 500 — saturating Δ of the near-pole parity at ~1/β and - # flooring the other at |Δ|·β — the Δ-mixing defect extended precision removes. - # Double64 arithmetic (eps ~ 5e-33) removes it outright; the resolved - # band stays Float64 (z ≤ ztrk there, solves well-conditioned). + # Damped-zone steps have cond ~ z ≫ 1; their structured LU backward error mixes u_small and u_big + # by ~eps·ρS²/2·‖u_big‖/‖u_small‖ (≈1e-4 at |Q| = 500 in Float64), so that zone runs in Double64. CTd = Complex{Double64} phd = CTd(cos(Double64(θ)), sin(Double64(θ))) 𝔐d(s) = phd * Matrix(ode_matrix(CTd, params, Q, phd * Double64(s))) - # --- Schedule: geometric where damped, growth-capped where resolved. --- - # No adaptive controller (three generations died on estimator artifacts); - # the step law is derived from the local mode structure instead. At each - # step the eigenvalues of 𝔐(s) give the two backward-growing exponential - # rates g (Re λ < 0, excluding the algebraic power-pair rates ~ r/s): - # - # damped zone (g_min·c·s > 8 for all growers): h = -c·s. All growing - # content — including the O(smax_tol) fast-direction contamination of - # the series data — sits at z > 8 where Radau DAMPS it - # (|R| ≈ 2/z). Slow-mode global error ≈ 10²c³ → c = (rtol/100)^{1/3}; - # step count ~ ln(S/s_m)/c, growing only logarithmically with S. - # - # resolved band (some grower at z ≲ 8): genuine backward growth must be - # tracked and removed. h = -min(c·s, 0.3/g_max) keeps z ≤ 0.3 so the - # DISCRETE growing eigendirection matches the continuous one to - # O(z²) ~ 1% (an orthogonal purge against a frame misaligned by δ - # leaks δ·content — with e-fold budget Φ ≤ 2.5 the cycle gain - # e^Φ·δ < 0.2 and contamination stays at the rounding floor). The - # frame F is carried CONTINUOUSLY with the same Radau steps + QR - # (backward-attracting ⇒ self-correcting), so no re-extraction cost. - # - # The band is entered where the slowest grower's rate drops. On the real - # axis with imaginary Q that is the Υ-family turning point x² = −Q²(G+KF), - # where the decaying frame cannot be identified and the march fails; the - # default θ = arg(Q)/4 keeps the turning point off the contour. + # Step law, from the local growth rates g of 𝔐(s): + # damped zone (every grower has g·c·s > 8): h = −c·s with c = (rtol/100)^{1/3}, so the step + # count grows only like ln(S/s_m); + # resolved band: h = −min(c·s, ztrk/g_max), with the decaying frame F carried by the same + # steps and purged from W every `purge_budget` e-folds. + # On the real axis with imaginary Q the band entry lands on the turning point x² = −Q²(G+KF), + # where F cannot be identified; the default θ keeps it off the contour. c = clamp(cbrt(rtol / 100.0), 2e-5, 2e-3) - # --- Phase 1: damped zone, W in Double64 (see the Double64 comment above). --- - # First purge (at S) and all damped-zone steps run in extended precision; - # on resolved-band entry W drops back to Float64 for phase 2. + # Damped zone, in Double64 from the first purge at S to the resolved-band entry. Wd = CTd.(W) let Floc = decaying_pair(params, Q, θ, S; growth=growth, seed=seed, dp_res=dp_res) Fd = CTd.(Floc) @@ -305,14 +219,12 @@ function march_boundary(params::GGJParameters, Q::ComplexF64, θ::Float64, end W = ComplexF64.(Wd) - # --- Phase 2: resolved band (Float64, carried frame + purges). --- + # Resolved band, in Float64 with the carried frame. Φ = 0.0 F = Matrix{ComplexF64}(undef, 6, 2) have_F = false while s > s_m + 1e-12 * S - # Backward-growing exponential rates from the frozen-coefficient - # spectrum (Re λ < 0 ⇒ grows as s decreases); rates ≲ 10/s are the - # algebraic power pair, not exponential growers. + # Backward-growing rates (Re λ < 0); rates ≲ 10/s belong to the algebraic power pair. λs = eigvals(Matrix(𝔐(s))) gmin, gmax = Inf, 0.0 for λ in λs @@ -344,16 +256,9 @@ function march_boundary(params::GGJParameters, Q::ComplexF64, θ::Float64, nstep += 1 nstep > 5_000_000 && error("march_boundary: step limit exceeded (s=$s)") end - # The boundary basis must span the traces AT s_m of the solutions that - # decay AT INFINITY — which, after the mode families morph around - # s ~ |Q|, is NOT the same subspace as the locally-decaying pair at s_m. - # The carried frame F is exactly the marched ∞-decaying pair (it enters - # the resolved band before the morphing region and tracks the subspace - # through it), so it IS the correct E-basis; re-extracting locally at - # s_m substitutes the wrong subspace and corrupts Δ at O(1) on - # extreme-coefficient surfaces. Local extraction remains only as the - # fallback when the march never entered the resolved band (no morphing - # crossed under resolution — the subspaces then coincide). + # E must span the solutions that decay at infinity, which differ from the locally decaying pair at + # s_m once the mode families morph (s ~ |Q|); the carried F is that subspace. Local extraction is + # the fallback when the march never entered the resolved band. if have_F W .-= F * (F' * W) else @@ -380,9 +285,7 @@ function boundary_basis(params::GGJParameters, Q::ComplexF64, return Us, Ub, E, _basis_cond(Us, Ub, E) end -# Driver: series radius S, BVP edge s_m, march S → s_m, then the Hermite Galerkin BVP on -# [0, s_m] with the far-field state v(s_m) = Us + Δ·Ub + c₁E₁ + c₂E₂ (Galerkin.jl, -# `_assemble_and_solve_point!`). +# Driver: series radius S, BVP edge s_m, march S → s_m, Hermite BVP on [0, s_m]. """ RaySolveResult @@ -447,11 +350,8 @@ function solve_ray(params::GGJParameters, Q::ComplexF64; Sv = S end - # Beyond s_m the solution is pure power law, carried by the quotient march; for small |Q| (s_m ≳ S) no march is needed. - # s_m: where every exponential solution family has decayed ≥ 45 e-folds from the origin, computed from the actual - # frozen-coefficient spectrum (the asymptotic ρs rate is wrong near the - # origin for extreme-coefficient surfaces, where the Υ-family rate - # √|Q(G+KF)| dominates and kills exponential content within s ~ O(1)). + # s_m: where every exponential family has decayed 45 e-folds from the origin, from the local spectrum. + # When s_m ≳ S (small |Q|) the series data are applied at S directly. s_m = let acc = 0.0, sprev = 0.0, out = Sv for sk in exp10.(range(-2, log10(Sv); length=400)) gdec = Inf @@ -523,12 +423,10 @@ end Rotated-ray implementation of the [`solve_inner_profile`](@ref) interface. `Δ` and the layer-center fields come from the solve at θ = arg(Q)/4; x = 0 lies on every contour, so -Ψ(0), Ξ(0) there are the real-axis values. By default only those center values are -returned (`x = [0.0]`, one-row `Ψ`, `Ξ`; `certΔ = NaN`), which is all the penetrated field -needs. With `real_profiles = true` the fields across the layer come from an extra θ = 0 -re-solve on the real axis, and the θ = 0 vs θ = arg(Q)/4 agreement of Δ₊ is returned as `certΔ` -(a runtime certificate; warns above `certify_rtol`). `npc` sets the profile points per mesh -cell; extra keywords forward to [`solve_ray`](@ref) (θ is fixed by the method — do not pass it). +Ψ(0), Ξ(0) are the real-axis values, and by default only they are returned (`x = [0.0]`, +`certΔ = NaN`). With `real_profiles = true` the fields across the layer come from an extra +θ = 0 solve (`npc` points per cell), and the relative difference of its Δ₊ is `certΔ`, +warned above `certify_rtol`. Other keywords forward to [`solve_ray`](@ref), except θ. """ function solve_inner_profile(::_BareGGJ{:ray}, params::GGJParameters, γ::Number; real_profiles::Bool=false, npc::Int=8, certify_rtol::Float64=1e-3, kwargs...) @@ -550,8 +448,7 @@ end Reconstruct (Ψ, Ξ, Υ) on the solution contour from the Hermite nodal solution, `npc` points per cell; each field is `npts × 2` with columns (even, odd) as in `Δ`, and `x = e^{iθ}s`. -For rotated solves the fields live on the ray — continuation back to real x is a -separate (unstable) problem, by design. +For rotated solves the fields live on the ray, not the real axis. """ function solution_profile(res::RaySolveResult; npc::Int=8) prof = _solution_profile(res.ws; npc=npc) @@ -587,12 +484,10 @@ end """ delta_convergence(params, Q; verbose=true, kwargs...) -> (; Δ, spread, base, table) -Error bar for the matching data: solve at the baseline, then re-solve with each -numerical knob perturbed on an independent axis (contour angle θ, mesh resolution, -series order/radius, march tolerance, handoff radius, purification e-folds — see -`variations` below) and report the relative change of (Δ₊, Δ₋) per knob. θ is perturbed -outward only: inward moves toward the x² ≈ −Q²(G+KF) pseudo-resonance and measures the -perturbed solve, not the baseline. `spread` is the per-parity worst case over all knobs. +Error bar for the matching data: re-solve with each numerical knob perturbed in turn (contour +angle, mesh, series order and radius, march tolerance, handoff radius, purification e-folds) and +report the relative change of (Δ₊, Δ₋); `spread` is the worst case per parity. θ moves outward +only, away from the pseudo-resonance x² = −Q²(G+KF). """ function delta_convergence(params::GGJParameters, Q::ComplexF64; verbose::Bool=true, kwargs...) base = solve_ray(params, Q; kwargs...) From 30044cc5faced3993e70d3e876d14b96168f4065 Mon Sep 17 00:00:00 2001 From: Matthew Pharr Date: Mon, 19 Oct 2026 14:50:04 +0200 Subject: [PATCH 06/12] InnerLayer - DOCS - Correct citations and prune references to previous states of the code --- docs/src/inner_layer.md | 63 +++++---- src/ForceFreeStates/CoreTypes.jl | 2 +- src/ForceFreeStates/Matching/MatchProblem.jl | 2 +- src/ForceFreeStates/Matching/ResonantMatch.jl | 4 +- src/InnerLayer/GGJ/GGJ.jl | 35 ++--- src/InnerLayer/GGJ/GGJParameters.jl | 25 ++-- src/InnerLayer/GGJ/Galerkin.jl | 129 +++++++++++------- src/InnerLayer/GGJ/InnerAsymptotics.jl | 102 ++++---------- src/InnerLayer/GGJ/Ray.jl | 46 ++++--- src/InnerLayer/GGJ/Reference.jl | 21 +-- src/InnerLayer/GGJ/Shooting.jl | 78 +++++------ src/InnerLayer/InnerLayerInterface.jl | 38 ++---- src/Tearing/Dispersion/CoupledFullMatch.jl | 8 +- src/Tearing/Runner/run_slayer.jl | 2 +- 14 files changed, 253 insertions(+), 302 deletions(-) diff --git a/docs/src/inner_layer.md b/docs/src/inner_layer.md index 42295b6a6..8c30cf7ce 100644 --- a/docs/src/inner_layer.md +++ b/docs/src/inner_layer.md @@ -35,7 +35,7 @@ The GGJ layer equations (GWP2016 Eq. 11 ≡ GW2020 Eq. 1) couple the perturbed f the layer variables ``\Xi``, ``\Upsilon`` in the scaled distance ``x`` from the rational surface. Their equilibrium coefficients ``E, F, G, H, K`` (GWP2016 Eq. A8) are held in [`GGJParameters`](@ref InnerLayer.GGJParameters). A physical growth rate ``\gamma`` maps to the -scaled ``Q`` by [`inner_Q`](@ref InnerLayer.inner_Q) (GWP2016 Eqs. A14–A15), and +scaled ``Q`` by [`inner_Q`](@ref InnerLayer.inner_Q) (GWP2016 Eqs. A11, A14–A16), and [`rescale_delta`](@ref InnerLayer.rescale_delta) returns the matching data to physical units. The model requires Mercier stability, ``D_I < 0`` ([`mercier_di`](@ref InnerLayer.mercier_di), GWP2016 Eq. A9), so that at large ``x`` the solutions include two power laws (GW2020 Eq. 49). @@ -46,14 +46,15 @@ Eqs. (34)–(35). Parity is that of the displacement ``\Xi`` (GWP2016 Eq. 34; Pl Dewar, J. Comput. Phys. **115**, 530 (1994), Eqs. 32–33): ``\Delta_+`` is even, ``\Psi(0)=\Xi'(0)=\Upsilon'(0)=0``, the **interchange** channel; ``\Delta_-`` is odd, ``\Psi'(0)=\Xi(0)=\Upsilon(0)=0``, the **tearing** channel. Positional pairs, such as `deltar` in -the matching and `RaySolveResult.Δ`, are always ordered ``(\Delta_+, \Delta_-)``, as in GWP2016 -Eq. (38); `InnerLayerResponse` names them `interchange` and `tearing`. +the matching and `RaySolveResult.Δ`, are always ordered ``(\Delta_+, \Delta_-)``, like the +unknowns ``d_\pm`` of GWP2016 Eq. (38) and Pletzer, Bondeson & Dewar Eqs. 83, 85; +`InnerLayerResponse` names them `interchange` and `tearing`. ## Numerical method !!! note "Benchmark surface used in the figures" - The figures use the ``q = 4`` surface of the DIII-D-like `resistive_resmets` benchmark, - frozen into [`q4_surface_benchmark`](@ref InnerLayer.q4_surface_benchmark) + The figures use the ``q = 4`` DIII-D-like surface of + [`q4_surface_benchmark`](@ref InnerLayer.q4_surface_benchmark) (``S \approx 4.6\times10^{6}``, ``D_I \approx -0.31``). ### Solver backends @@ -65,12 +66,12 @@ The `GGJ` model exposes three solvers through the `solver` type parameter of | backend | method | robust regime | |:--------|:-------|:--------------| | `:shooting` | backward stable shoot from ``X_\mathrm{max}\to 0`` | ``\lvert Q\rvert \ll 1`` | -| `:galerkin` | Hermite-cubic finite-element (real axis) | drift onset ``\lvert Q\rvert \sim 1``; 1% error by ``\lvert Q\rvert \sim 4`` | +| `:galerkin` | Hermite-cubic finite-element (real axis) | surface- and ``\arg Q``-dependent; see [Choosing a backend](@ref) | | `:ray` (default) | rotated contour: inward-marched far-field condition + Hermite-cubic BVP | ``\lvert Q\rvert \sim 500`` on/near the imaginary axis | Rotation and resistivity scans live on the imaginary-``Q`` axis, where the pseudo-resonance at -``x^2 = -Q^2(G+KF)`` sits on the real-``x`` path. There `:shooting` and `:galerkin` lose -accuracy beyond ``|Q| \sim 1`` and ``|Q| \sim 4`` respectively (the poles of ``\Delta(Q)`` +``x^2 = -Q^2(G+KF)`` sits on the real-``x`` path. On the ``q = 4`` surface there `:shooting` and +`:galerkin` lose accuracy beyond ``|Q| \sim 1`` and ``|Q| \sim 4`` respectively (the poles of ``\Delta(Q)`` themselves lie near the real-``Q`` axis): ![Relative error of the :shooting and :galerkin backends against the :ray reference along the imaginary-Q axis, on the q=4 benchmark surface. Each curve's crossing of the 1% line marks that method's practical reach.](figures/inner_layer/backend_regime_map.png) @@ -94,8 +95,7 @@ pseudo-resonance off the contour; ``\theta = 0`` is a real-axis solve. On ``[0, s_m]`` the system is solved with the `:galerkin` backend's Hermite-cubic assembly (GWP2016 Eq. 32) written on the ray, ``A u_{ss} + e^{i\theta}B u_s + e^{2i\theta}C u = 0``, -with the parity conditions at ``s = 0``. Instead of resonant and extension cells, the far end -carries the point condition +with the parity conditions at ``s = 0``. The far end carries the point condition ```math v(s_m) = U_s + \Delta\, U_b + c_1 E_1 + c_2 E_2 , @@ -108,16 +108,15 @@ Each cell resolves the local WKB rate, with a minimum cell count for small ``|Q| ### Far-field boundary and the inward march The boundary data come from the same `inps` Wasow basis as the other backends (GW2020 -Eqs. 3–52), evaluated at the radius ``S`` where its residual is below tolerance +Eqs. 3–53), evaluated at the radius ``S`` where its residual is below tolerance ([`pick_smax`](@ref InnerLayer.pick_smax)). At large ``|Q|``, ``S`` lies far beyond ``s_m``, and the power pair is marched inward by 2-stage Radau IIA modulo the decaying pair, the subspace in -which ``\Delta`` is defined. The decaying pair grows under backward integration, so an explicit -method would need ``O(\rho S^2)`` steps. Radau's stability function decays as ``2/z``, so steps -with every growing mode at ``z > 8`` damp those directions while the slowly varying power pair -stays resolved. Nearer ``s_m`` the march resolves the growing directions, carries the decaying -frame, and projects it out periodically. The damped zone runs in `Complex{Double64}`: in -`Float64` the ill-conditioned implicit solves mix the power pair at about ``10^{-4}`` at -``|Q| = 500``. +which ``\Delta`` is defined. The decaying pair grows under backward integration at a rate +``\sim\rho s``. Radau's stability function decays as ``2/z``, so steps with every growing mode at +``z > 8`` damp those directions while the slowly varying power pair stays resolved; the step count +grows only like ``\ln(S/s_m)``. Nearer ``s_m`` the march resolves the growing directions, carries +the decaying frame, and projects it out periodically. The damped zone runs in `Complex{Double64}` +because its ill-conditioned implicit solves mix the power pair at a level ``\sim\epsilon\rho S^2``. On the real axis with imaginary ``Q`` the switch to resolved steps lands on the pseudo-resonance, a turning point where the decaying directions cannot be identified; the @@ -163,16 +162,30 @@ worst case is ``\sim 5\times10^{-6}`` for ``\Delta_+`` and ``\sim 6\times10^{-7} Across machines and BLAS builds the values reproduce to ``\sim 10^{-5}`` relative, hence the five significant figures above. -![Relative change of Δ at Q = 500i under independent perturbations of each numerical knob (contour angle, mesh resolution, series order/radius, march tolerance, handoff radius, purification depth). The worst-case spread is the reported error bar.](figures/inner_layer/convergence_Sinvariance.png) +![Relative change of Δ at Q = 500i under independent perturbations of each numerical knob (contour angle, mesh resolution, series order/radius, march tolerance, BVP edge s_m, decaying-pair separation). The worst-case spread is the reported error bar.](figures/inner_layer/convergence_Sinvariance.png) ## Choosing a backend -`:ray` is the **default** — `GGJModel()` constructs `GGJModel{:ray}()`. It is -the correct choice for ``|Q| \gtrsim 1`` and for any ``Q`` near the imaginary -axis. `:galerkin` remains available and may be faster for very small real -``|Q|``, but note the backends take disjoint numerical-knob keywords: pass -`GGJModel(solver=:galerkin)` explicitly when supplying the Galerkin `nx`/`xfac` -knobs — passing them to the default `:ray` backend throws a `MethodError`. +`:ray` is the **default** — `GGJModel()` constructs `GGJModel{:ray}()` — and the recommended +backend for every ``Q``. It uses the same Hermite-cubic weak form as `:galerkin`; they differ in +where and how the far-field condition is imposed. `:galerkin` imposes it on the real axis through +resonant and extension cells at the radius where the series residual reaches ``10^{-7}``, on a +fixed `nx`-cell grid. `:ray` takes the series data where the residual reaches `smax_tol` = +``10^{-9}`` ([`pick_smax`](@ref InnerLayer.pick_smax)), marches them inward to ``s_m``, where every +exponential family has decayed 45 e-folds from the origin, and resolves the local WKB rate in +every cell on ``[0, s_m]``. Both radii are computed per solve; `S`, `smax_tol` and `sm_fac` +override them, and [`delta_convergence`](@ref InnerLayer.delta_convergence) perturbs them to give +an error bar. + +`:galerkin` takes a few milliseconds per solve, 3–60 times less than `:ray`, but its accuracy +depends on the surface and on ``\arg Q`` even at small ``|Q|``. Against a tightened `:ray` +reference, on the GW2020 Eq. (55) surface it errs by ``7\times10^{-5}`` at ``Q = 0.1`` and +``3\times10^{-3}`` at ``Q = 0.3``; near ``\arg Q = 157.5^\circ`` it errs by order unity at +``|Q| = 0.1`` on that surface and by 0.4 at ``|Q| = 0.3`` on the ``q = 4`` surface. `:ray` held +``2\times10^{-6}`` on all three surfaces tested, for ``|Q|`` from 0.01 to 1. + +The backends take disjoint numerical-knob keywords: pass `GGJModel(solver=:galerkin)` explicitly +when supplying the Galerkin `nx`/`xfac` knobs; passing them to `:ray` throws a `MethodError`. ```julia using GeneralizedPerturbedEquilibrium.InnerLayer diff --git a/src/ForceFreeStates/CoreTypes.jl b/src/ForceFreeStates/CoreTypes.jl index 4d87f87a0..ef384af7b 100644 --- a/src/ForceFreeStates/CoreTypes.jl +++ b/src/ForceFreeStates/CoreTypes.jl @@ -205,7 +205,7 @@ gpec.toml. # --- DRIVEN (RPEC) outer↔inner asymptotic matching (rmatch match_rpec port) --- gal_match_flag::Bool = false # enable the RPEC inner-layer matching: solve the coil-driven matched ξ(ψ) from the gal Δ′ + the inner-layer Δ(Q). Requires gal_rpec_flag=true. gal_ideal_flag::Bool = false # within the match, build the IDEAL solution: skip the inner-layer Δ, use bare coil columns (cout=0). Mirrors Fortran rmatch coil%ideal_flag (the EL reference). eta/rho/rotation ignored. - gal_inner_solver::String = "ray" # inner-layer Δ backend for the match: "ray" (rotated contour + inward march, certified Δ at the optimal θ = arg(Q)/4; robust for |Q| ≳ 1) or "galerkin" (Hermite-cubic inps; drifts for |Q| ≳ 1) + gal_inner_solver::String = "ray" # inner-layer Δ backend for the match: "ray" (rotated contour + inward march; recommended for every Q) or "galerkin" (real-axis Hermite FEM; accuracy depends on the surface and arg Q) # --- Inner-layer "galerkin" backend overrides (gal_inner_solver = "galerkin"; unset keeps the backend default) --- gal_inner_xfac::Union{Nothing,Float64} = nothing # asymptotic-matching radius multiplier gal_inner_nx::Union{Nothing,Int} = nothing # inner-layer grid cells diff --git a/src/ForceFreeStates/Matching/MatchProblem.jl b/src/ForceFreeStates/Matching/MatchProblem.jl index 972804c6e..47e7835ae 100644 --- a/src/ForceFreeStates/Matching/MatchProblem.jl +++ b/src/ForceFreeStates/Matching/MatchProblem.jl @@ -143,7 +143,7 @@ function _compute_match(prob::MatchProblem, model::InnerLayer.GGJModel) deltar[i, 2] = inner.Δ[2] profΨ, profΞ, xg = inner.Ψ, inner.Ξ, inner.x resc = inner.rescale # inner big-branch amplitude → outer δψ normalization - # b_m = 2πi·χ₁·(m−nq)·ξ_m with m−nq = −n·q′·dψdx·X and Ψ = XΞ (GWP2016 Eq. 16) ⇒ b_m = scale·resc·Ψ. + # b_m = 2πi·χ₁·(m−nq)·ξ_m with m−nq = −n·q′·dψdx·X and Ψ = XΞ at leading order (GWP2016 Eqs. 16, 27; Ψ normalization Eq. A17) ⇒ b_m = scale·resc·Ψ. scale = -2π * chi1 * im * nn * sings[i].q1 * inner.dψdx pen[i, 1] = scale * profΨ[1, 1] * resc # X = 0, even parity (Ψ(0) = 0) pen[i, 2] = scale * profΨ[1, 2] * resc # odd parity diff --git a/src/ForceFreeStates/Matching/ResonantMatch.jl b/src/ForceFreeStates/Matching/ResonantMatch.jl index bb96858dc..0b3e6e882 100644 --- a/src/ForceFreeStates/Matching/ResonantMatch.jl +++ b/src/ForceFreeStates/Matching/ResonantMatch.jl @@ -1,6 +1,6 @@ # ResonantMatch.jl # -# Matching result and the 4·msing outer↔inner system (rmatch match_rpec; Wang et al. 2020 PoP 27 122509, Eq. 11). +# Matching result and the 4·msing outer↔inner system (rmatch match_rpec; Wang et al., Phys. Plasmas 27, 122503 (2020), Eq. 11). """ MatchResult @@ -51,7 +51,7 @@ function _match_system(dp_raw::AbstractMatrix, dp_coil::AbstractMatrix, deltar:: idx2 = 2ising idx3 = idx1 + 2msing idx4 = idx2 + 2msing - delta1 = deltar[ising, 1] # Δ₊; rows idx3, idx4 of cin are d₊, d₋ (GWP2016 Eqs. 36–37) + delta1 = deltar[ising, 1] # Δ₊; unknowns idx3, idx4 (cin rows 2i−1, 2i) are d₊, d₋ (GWP2016 Eqs. 36–37) delta2 = deltar[ising, 2] # Δ₋ mat[idx1, idx1] = 1 mat[idx2, idx2] = 1 diff --git a/src/InnerLayer/GGJ/GGJ.jl b/src/InnerLayer/GGJ/GGJ.jl index 941a319a4..eff0f68d9 100644 --- a/src/InnerLayer/GGJ/GGJ.jl +++ b/src/InnerLayer/GGJ/GGJ.jl @@ -1,36 +1,29 @@ # GGJ.jl # -# Glasser–Greene–Johnson resistive inner-layer model. Provides three -# interchangeable solvers selected via the `solver` type-parameter of -# `GGJModel`: +# Glasser–Greene–Johnson resistive inner-layer model, with three solvers selected by the +# `solver` type parameter of `GGJModel`: # -# - `:shooting` – stable backward shoot from X_max → 0; -# numerically stable only for |Q| ≪ 1, should not be used -# - `:galerkin` – Hermite-cubic finite element method with resonant/extension -# matching cells (GWP2016 Sec. III); degrades for |Q| ≳ 1 -# - `:ray` – rotated-contour solve (Ray.jl): far-field series + inward march, -# and the same Hermite assembly with a point far-field condition; -# robust to |Q| ~ 500 on/near the imaginary axis +# - `:shooting` – backward shoot from X_max → 0; valid only for |Q| ≪ 1 (tests and comparisons) +# - `:galerkin` – Hermite-cubic finite elements with resonant/extension matching cells +# (GWP2016 Sec. III); accuracy depends on the surface and arg Q +# - `:ray` – the same Hermite assembly on the rotated contour (Ray.jl), with the far-field +# condition marched in from where the series converges; robust to |Q| ~ 500 # -# They return the parity-projected matching data Δ± of GWP2016 Eqs. (34)–(35). Parity is -# that of the displacement Ξ: Δ₊ (even) is the interchange channel, Δ₋ (odd) the tearing -# channel; positional pairs are always ordered (Δ₊, Δ₋), as in GWP2016 Eq. (38). +# They return the matching data Δ± of GWP2016 Eqs. (34)–(35). Parity is that of the displacement Ξ: +# Δ₊ (even) is the interchange channel, Δ₋ (odd) the tearing channel. Positional pairs are always +# ordered (Δ₊, Δ₋), as d₊, d₋ in GWP2016 Eq. (38) and Pletzer, Bondeson & Dewar (1994) Eqs. 83, 85. # -# Equation references throughout this module use two source papers: +# Main source papers, cited by equation number throughout: # # GWP2016 — A. H. Glasser, Z. R. Wang & J.-K. Park, "Computation of resistive # instabilities by matched asymptotic expansions", Phys. Plasmas 23, -# 112506 (2016). Inner-region equations (Eq. 11), matrix form -# A Ψ'' + B Ψ' + C Ψ = 0 (Eqs. 12–15), singular-Galerkin weak form -# (Eq. 32), grid packing (Eq. 33), matching data (Eqs. 34–35), -# dimensionless parameters / scale factors (Appendix, Eqs. A8–A15). +# 112506 (2016). Inner-region equations (Eq. 11), singular-Galerkin method +# (Sec. III), matching data (Eqs. 34–35), scale factors (Appendix, Eqs. A8–A16). # # GW2020 — A. H. Glasser & Z. R. Wang, "Asymptotic solutions and convergence # studies of the resistive inner region equations", Phys. Plasmas 27, # 012506 (2020). Wasow construction of the large-x asymptotic basis # (Eqs. 1–55); implemented in InnerAsymptotics.jl. -# -# The inner-region equations are identical in both: GW2020 Eq. (1) ≡ GWP2016 Eq. (11). module GGJ @@ -50,7 +43,7 @@ import ..solve_inner, ..solve_inner_profile Glasser–Greene–Johnson resistive inner-layer model. `S` selects the solver backend: `:ray` (default; rotated contour with an inward-marched far-field condition, robust at large |Q|), `:galerkin` (real-axis Hermite FEM with resonant/extension matching -cells; degrades for |Q| ≳ 1), or `:shooting` (|Q| ≪ 1 only). Backend keywords given at +cells; accuracy depends on the surface and arg Q, even at small |Q|), or `:shooting` (|Q| ≪ 1 only). Backend keywords given at construction, e.g. `GGJModel(; solver=:galerkin, nx=1280)`, apply to every solve. ## Fields diff --git a/src/InnerLayer/GGJ/GGJParameters.jl b/src/InnerLayer/GGJ/GGJParameters.jl index 4acca7fef..3d5f59e8b 100644 --- a/src/InnerLayer/GGJ/GGJParameters.jl +++ b/src/InnerLayer/GGJ/GGJParameters.jl @@ -11,9 +11,9 @@ Dimensionless parameters of the Glasser–Greene–Johnson inner-layer model at a single rational surface, plus the local Alfvén/resistive timescales needed to scale the matching data back to physical Δ. The equilibrium coefficients `E, F, G, H, K, M` are the flux-surface averages defined in -GWP2016 Eq. (A8); they enter the inner-region equations (Eq. 11). +GWP2016 Eq. (A8); E, F, G, H, K enter the inner-region equations (Eq. 11). -Fields: +## Fields | field | meaning | |:------- |:-------------------------------------------------------------- | @@ -22,10 +22,10 @@ Fields: | `G` | Coupling coefficient (curvature × pressure gradient) | | `H` | Pfirsch–Schlüter coefficient | | `K` | Glasser parameter | -| `M` | Mercier-related auxiliary parameter (held but not used here) | +| `M` | Inertia factor (A8; enters K and Q₀, X₀); held, not used here | | `taua` | Local Alfvén time at the rational surface | | `taur` | Local resistive time at the rational surface | -| `v1` | Linear scale factor used in the V₁ rescaling | +| `v1` | Coordinate scale: inner X = v₁·δψ/X₀; enters `rescale_delta` | | `ising` | Index of the singular surface (traceability only) | The growth rate `γ` is not stored here; it is a separate argument to `solve_inner`. @@ -79,29 +79,30 @@ sfac(p::GGJParameters) = p.taur / p.taua """ x0(p::GGJParameters) -> Float64 -Inner-layer length scale `X₀ = S^(−1/3)` (GWP2016 Eq. A14); physical `x = X₀ X`. +Inner-layer length scale `X₀ = S^(−1/3)` (GWP2016 Eq. A16); physical `x = X₀ X` (Eq. A11). """ x0(p::GGJParameters) = sfac(p)^(-1.0 / 3.0) """ q0(p::GGJParameters) -> Float64 -Growth-rate scale `Q₀ = X₀ / τ_A` (GWP2016 Eq. A15); physical rate `= Q₀ Q`. +Growth-rate scale `Q₀ = X₀ / τ_A` (GWP2016 Eq. A16); physical rate `= Q₀ Q` (Eq. A11). """ q0(p::GGJParameters) = x0(p) / p.taua """ inner_Q(p::GGJParameters, γ::Number) -> ComplexF64 -Scaled inner-layer growth rate `Q = γ / Q₀` (GWP2016 Eq. A15). +Scaled inner-layer growth rate `Q = γ / Q₀` (GWP2016 Eq. A11). """ inner_Q(p::GGJParameters, γ::Number) = ComplexF64(γ) / q0(p) """ rescale_delta(Δ, p::GGJParameters) -> SVector{2,ComplexF64} -Rescale the matching data to physical Δ by `S^(2√(−D_I)/3) · v₁^(2√(−D_I))` -(GWP2016 Sec. IV), element-wise on `(Δ_odd, Δ_even)`. +Rescale the matching data to physical Δ by `S^(2√(−D_I)/3) · v₁^(2√(−D_I))`, element-wise +on the pair (Δ₊, Δ₋). The factor X₀^(−2√(−D_I)) = S^(2√(−D_I)/3) is Wang et al., Phys. Plasmas +27, 122503 (2020), text after Eq. 11. """ function rescale_delta(Δ::AbstractVector, p::GGJParameters) s = sfac(p) @@ -110,8 +111,6 @@ function rescale_delta(Δ::AbstractVector, p::GGJParameters) return SVector{2,ComplexF64}(Δ[1] * fac, Δ[2] * fac) end -# Profile conversions shared by the solve_inner_profile backends: δψ per unit inner -# coordinate X = v₁·δψ/X₀, and the big-branch (μ₋ = −1/2−p₁) amplitude rescale to the -# outer δψ-normalization, resc = (v₁/X₀)^(−μ₋) — the companion of rescale_delta's -# (v₁/X₀)^(2p₁) = (v₁/X₀)^(μ₊−μ₋). +# Profile conversions for solve_inner_profile: δψ per unit inner coordinate (X = v₁·δψ/X₀) and the +# large-solution amplitude rescale (v₁/X₀)^(1/2+p₁) to the outer δψ normalization. _profile_conversions(p::GGJParameters) = (; dψdx=x0(p) / p.v1, rescale=(p.v1 / x0(p))^(0.5 + p1(p))) diff --git a/src/InnerLayer/GGJ/Galerkin.jl b/src/InnerLayer/GGJ/Galerkin.jl index a5bae0c39..552177c65 100644 --- a/src/InnerLayer/GGJ/Galerkin.jl +++ b/src/InnerLayer/GGJ/Galerkin.jl @@ -4,8 +4,8 @@ # Sec. III singular-Galerkin method: the half-domain weak form (Eq. 32) on a packed grid # (Eq. 33), parity conditions at x = 0, and resonant/extension cells at x_max supplying the # matching data (Eqs. 34–35). Fortran deltac configuration: "resonant" + noexp + inps, -# Hermite basis, mpert = 3 (Ψ, Ξ, Υ). The equations are assembled as I·u'' − V·u' − U·u = 0 -# with (I, V, U) = (A, −B, −C) of GWP2016 Eq. 12; see `_physical_uv`. +# Hermite basis, mpert = 3 (Ψ, Ξ, Υ). `_assemble_and_solve_point!` reuses the assembly on the +# rotated ray with a point far-field condition (Ray.jl). using LinearAlgebra using FastGaussQuadrature: gausslobatto @@ -29,7 +29,7 @@ function _physical_uv(params::GGJParameters, Q::ComplexF64, x::Number) Imat = @SMatrix ComplexF64[1 0 0; 0 q2 0; 0 0 q] - # U = −C (GWP2016 Eq. 15) and V = −B (Eq. 14), rows pre-scaled as in the Fortran. + # U = −C (GWP2016 Eq. 15) and V = −B (Eq. 14), rows scaled by diag(1, Q², Q) like `Imat`. #! format: off U = @SMatrix ComplexF64[ q (-q * x) 0 @@ -68,8 +68,8 @@ function _hermite(x::Real, x0::Real, x1::Real) return pb, qb end -# Grid packing (GWP2016 Eq. 33): pfac > 1 concentrates nodes near X = 0, pfac = 1 is uniform, -# 0 < pfac < 1 packs toward the edge. +# Grid packing: pfac > 1 concentrates nodes near X = 0 (GWP2016 Eq. 33), pfac = 1 is uniform, +# 0 < pfac < 1 packs toward the edge (Eq. 5). function _pack(nx::Int, pfac::Float64, side::String) xi = zeros(Float64, 2nx + 1) if side == "right" @@ -162,36 +162,66 @@ function _xmax_3level(params::GGJParameters, Q::ComplexF64; return (; xmax, dx1, dx2, cache) end -# Cell types of GWP2016 Fig. 1, toward x_max: normal Hermite cells (CT_NONE), extension cells -# blending the small resonant solution into the Hermite basis (CT_EXT2, CT_EXT1, CT_EXT), and the -# resonant cell (CT_RES) whose large-solution coefficient is the matching data. The half domain has -# one resonant cell; x = 0 carries the parity conditions. +# Cell types toward x_max (GWP2016 Sec. III text after Eq. 33; the outer-region analogue is Fig. 1): +# normal Hermite cells (CT_NONE), extension cells blending the asymptotic solutions into the Hermite +# basis (CT_EXT2, CT_EXT1, CT_EXT), and the resonant cell (CT_RES) whose large-solution coefficient is +# the matching data. x = 0 carries the parity conditions. @enum CellType CT_NONE CT_EXT2 CT_EXT1 CT_EXT CT_RES +""" + GalerkinCell + +One finite element of the Galerkin grid. + +## Fields + + - `etype` - Cell type (`CT_NONE`, `CT_EXT2`, `CT_EXT1`, `CT_EXT`, `CT_RES`). + - `x_left`, `x_right` - Cell end points. + - `x_lsode` - Upper limit of the resonant-cell integral and the x_max surface term (`CT_RES` only). + - `np` - Highest local Hermite slot per component: 3 for Hermite cells, 1 for `CT_EXT` (left node only), −1 for `CT_RES`. + - `map` - `(mpert, np+1)` local-to-global DOF map; `CT_EXT` appends a column of asymptotic DOFs, `CT_RES` holds only those. + - `emap` - Asymptotic DOF indices shared by `CT_EXT` and `CT_RES`; only `emap[1]` is active (noexp). +""" struct GalerkinCell etype::CellType x_left::Float64 x_right::Float64 - x_lsode::Float64 # right integration limit for res cell - np::Int # Hermite DOF count per component (-1 for res) - map::Matrix{Int} # (mpert, 0:np_eff) local-to-global DOF map - emap::Vector{Int} # extra (asymptotic) DOF indices (length 1 for noexp) + x_lsode::Float64 + np::Int + map::Matrix{Int} + emap::Vector{Int} end +""" + GalerkinWorkspace + +Grid, banded system and scratch buffers of one Galerkin solve. + +## Fields + + - `cells` - Grid cells from x = 0 outward. + - `ndim` - Number of global unknowns. + - `nx` - Number of cells. + - `kl` - Banded half-bandwidth (`ku = kl`). + - `mat` - `(2kl+ku+1, ndim, 2)` LAPACK banded matrices, one per parity (1 = even/Δ₊, 2 = odd/Δ₋). + - `rhs`, `sol` - `(ndim, 2)` right-hand sides and solutions per parity. + - `cell_mat_buf`, `cell_mat_ext_buf` - `(3, 3, 4, 4)` per-cell scratch for the Hermite and extension terms. + - `cell_rhs_ext_buf` - `(3, 4)` per-cell extension RHS scratch. + - `ab_buf`, `rhs_buf` - Scratch copies for the banded LU solve. +""" struct GalerkinWorkspace cells::Vector{GalerkinCell} ndim::Int nx::Int kl::Int - mat::Array{ComplexF64,3} # (ldab, ndim, 2) banded storage - rhs::Matrix{ComplexF64} # (ndim, 2) - sol::Matrix{ComplexF64} # (ndim, 2) - # Per-cell scratch buffers, zeroed with `fill!`. - cell_mat_buf::Array{ComplexF64,4} # (mpert=3, mpert, np+1=4, np+1=4) - cell_mat_ext_buf::Array{ComplexF64,4} # (3, 3, 4, 4) max over CT_EXT/EXT1/EXT2 - cell_rhs_ext_buf::Matrix{ComplexF64} # (3, 4) - ab_buf::Matrix{ComplexF64} # (ldab, ndim) scratch for banded LU - rhs_buf::Vector{ComplexF64} # (ndim,) scratch for banded solve + mat::Array{ComplexF64,3} + rhs::Matrix{ComplexF64} + sol::Matrix{ComplexF64} + cell_mat_buf::Array{ComplexF64,4} + cell_mat_ext_buf::Array{ComplexF64,4} + cell_rhs_ext_buf::Matrix{ComplexF64} + ab_buf::Matrix{ComplexF64} + rhs_buf::Vector{ComplexF64} end function _build_grid_and_workspace(nx::Int, xmax::Float64, dx1::Float64, dx2::Float64, @@ -250,7 +280,7 @@ function _galerkin_workspace(x_nodes::Vector{Float64}, etypes::Vector{CellType}) cell_np = if et == CT_NONE || et == CT_EXT1 || et == CT_EXT2 np elseif et == CT_EXT - 1 # method=true: left Hermite pair only + 1 extra + 1 # left-node Hermite pair only, plus one asymptotic DOF else # CT_RES -1 # no Hermite DOFs end @@ -303,7 +333,7 @@ function _galerkin_workspace(x_nodes::Vector{Float64}, etypes::Vector{CellType}) ndim = has_res ? imap : imap - 1 # noexp → ndim = imap (only emap[1] ≤ ndim); plain grid: Hermite DOFs only # Bandwidth - kl = mpert * (np + 1) + 1 - 1 # resonant method with noexp; +1-1 kept for indexing agreement + kl = mpert * (np + 1) # one cell's mpert·(np+1) DOFs ku = kl ldab = 2kl + ku + 1 @@ -346,7 +376,6 @@ function _gauss_quad!(cell_mat::Array{ComplexF64,4}, cell::GalerkinCell, pb, qb = _hermite(x, cell.x_left, cell.x_right) for ip in 0:np_cell, jp in 0:np_cell - # cell_mat[:,:,ip+1,jp+1] += w*(I*qb[ip]*qb[jp] + V*pb[ip]*qb[jp] + U*pb[ip]*pb[jp]) for jpert in 1:3, ipert in 1:3 cell_mat[ipert, jpert, ip+1, jp+1] += w * ( @@ -359,7 +388,7 @@ function _gauss_quad!(cell_mat::Array{ComplexF64,4}, cell::GalerkinCell, end end -# Extension cells (GWP2016 Fig. 1): the large resonant solution (column 1) is blended into the +# Extension cells (GWP2016 Sec. III): the large resonant solution (column 1) is blended into the # Hermite cubics with C¹ continuity as an extra DOF; the small one (column 2) drives the RHS. function _extension!(cell_mat::Array{ComplexF64,4}, cell_rhs::Matrix{ComplexF64}, cell::GalerkinCell, @@ -383,13 +412,9 @@ function _extension!(cell_mat::Array{ComplexF64,4}, cell_rhs::Matrix{ComplexF64} Imat, Umat, Vmat = _physical_uv(params, Q, x) pb, qb = _hermite(x, cell.x_left, cell.x_right) - # The asymptotic basis function in the ext cell uses Hermite blending - # at the right node: phi_j(x) = ua_j * pb[3] + dua_j * pb[4] - # (pb[3] = H_10, pb[4] = H_11 at right node) - - # (h_i, L*phi_j) for i=0:np_cell, j=1 (only large algebraic, noexp) - # and (phi_j^T, L*h_i) for the transpose - jp = 1 # only tid(1) = column 1 = large algebraic (with noexp) + # Extra DOF φ = ua₁(x_r)·H₁₀ + ua₁'(x_r)·H₁₁, the large solution Hermite-blended at the right + # node; assembles (hᵢ, Lφ), (φ, Lhᵢ) and (φ, Lφ). + jp = 1 # column 1 = large solution (noexp) ua1 = ua_bdy[:, jp] * pb[3] + dua_bdy[:, jp] * pb[4] dua1 = ua_bdy[:, jp] * qb[3] + dua_bdy[:, jp] * qb[4] @@ -409,7 +434,7 @@ function _extension!(cell_mat::Array{ComplexF64,4}, cell_rhs::Matrix{ComplexF64} term = transpose(dua2_s) * Imat * dua1 + transpose(ua2_s) * Vmat * dua1 + transpose(ua2_s) * Umat * ua1 cell_mat[1, 1, ep+1, ep+1] += w * term - # RHS: driving from small algebraic (column 2 = tid(4)) + # RHS: driven by the small solution (column 2) ua_drv = uax[:, 2] dua_drv = duax[:, 2] for ip in 0:np_cell @@ -501,7 +526,7 @@ function _assemble_and_solve!(ws::GalerkinWorkspace, for ix in 1:ws.nx cell = ws.cells[ix] - # Gauss quadrature for Hermite contribution (all cell types) + # Gauss quadrature for the Hermite contribution (all cells but CT_RES) if cell.np >= 0 np_eff = cell.np fill!(cell_mat, 0) @@ -554,7 +579,7 @@ function _assemble_and_solve!(ws::GalerkinWorkspace, end end - # IBP surface term [αᵢ A uⱼ'] at x_max (GWP2016 Eq. 32), kept because the resonant cell carries Δ. + # IBP surface term [αᵢ A uⱼ'] at x_max, dropped in GWP2016 Eq. 32 and kept here because the resonant cell carries Δ. res_cell = ws.cells[ws.nx] x_lsode = res_cell.x_lsode ua_xmax, dua_xmax = physical_ua_dua(cache, x_lsode) @@ -605,7 +630,7 @@ function _parity_bcs_and_solve!(ws::GalerkinWorkspace, params::GGJParameters, Q: cell1 = ws.cells[1] Imat0, _, _ = _physical_uv(params, Q, cell1.x_left) - # Restore surface term at x=0 (IBP boundary) + # IBP surface term at x = 0 for ipert in 1:mpert, jpert in 1:mpert i = cell1.map[ipert, 1] # ip=0 j = cell1.map[jpert, 2] # ip=1 @@ -674,10 +699,9 @@ end _assemble_and_solve_point!(ws, params, Q, θ, Us, Ub, E; nq=6) -> (Δraw, cexp) Hermite Galerkin solve on the all-`CT_NONE` grid of `ws` along the ray x = e^{iθ}s, with the -far-field condition imposed at the last node instead of resonant/extension cells: its state is -v = Us + Δ·Ub + c₁E₁ + c₂E₂, with Us, Ub, E given as (Ψ, Ξ, Υ, Ψ', Ξ', Υ') in x-derivatives. The last node's six -DOFs are replaced by (Δ, c₁, c₂) and tested in the same three directions, as the extension cell -does for the stock backend. Returns the raw Δ and decaying-pair coefficients per parity +far-field condition imposed strongly at the last node: its state is v = Us + Δ·Ub + c₁E₁ + c₂E₂, +with Us, Ub, E given as (Ψ, Ξ, Υ, Ψ', Ξ', Υ') in x-derivatives. The last node's six DOFs are +replaced by (Δ, c₁, c₂), tested in the same three directions. Returns the raw Δ and decaying-pair coefficients per parity (isol = 1 even/Δ₊, 2 odd/Δ₋); `ws.sol` holds the full nodal solution afterwards. """ function _assemble_and_solve_point!(ws::GalerkinWorkspace, params::GGJParameters, Q::ComplexF64, @@ -693,8 +717,8 @@ function _assemble_and_solve_point!(ws::GalerkinWorkspace, params::GGJParameters _scatter_cell!(ws, ws.cells[ix], cell_mat, ws.cells[ix].np) end - # Replaces GWP2016 ext/res cells: the far-field state is imposed strongly at the last node. - # Last cell as a dense 12×12 block, local DOF index 3·ip + ipert (ip = 0..3 Hermite slots). + # Last cell as a dense 12×12 block, local DOF index 3·ip + ipert (ip = 0..3 Hermite slots); the + # far-field state is imposed at its right node. cell = ws.cells[N] _gauss_quad!(cell_mat, cell, quad_nodes, quad_weights, params, Q; θ=θ) Kc = zeros(ComplexF64, 12, 12) @@ -746,13 +770,8 @@ function _assemble_and_solve_point!(ws::GalerkinWorkspace, params::GGJParameters return SVector(Δraw), SMatrix(cexp) end -# ----------------------------------------------------------------------- -# Reconstruct the inner-layer field profiles (Ψ, Ξ, Υ) from the solved -# Hermite DOFs over the bulk (Hermite) cells. The thin CT_EXT / CT_RES -# matching cells near xmax are skipped (their solution is carried by the -# asymptotic emap DOF, not the Hermite basis). Returns the grid `x` and the -# three fields for both parities (columns: 1 = even/Δ₊, 2 = odd/Δ₋). -# ----------------------------------------------------------------------- +# Profiles (Ψ, Ξ, Υ) from the Hermite DOFs, columns 1 = even/Δ₊, 2 = odd/Δ₋; CT_EXT/CT_RES cells are +# skipped because their solution lives in the asymptotic emap DOF. function _solution_profile(ws::GalerkinWorkspace; npc::Int=10) mpert = 3 # Every Hermite cell contributes npc points. @@ -831,9 +850,13 @@ Solve the GGJ inner-layer matching problem using the Hermite-cubic finite element (Galerkin) method (GWP2016 Sec. III), in the "resonant + noexp + inps" configuration. -Returns the parity-projected matching data (GWP2016 Eqs. 34–35) with the -`X₀^{2√(−D_I)}` physical rescaling applied, as an `InnerLayerResponse`: -`interchange` is the even-parity Δ₊ (isol = 1), `tearing` the odd-parity Δ₋ (isol = 2). +Returns the parity-projected matching data (GWP2016 Eqs. 34–35), rescaled by +[`rescale_delta`](@ref), as an `InnerLayerResponse`: `interchange` is the even-parity Δ₊ +(isol = 1), `tearing` the odd-parity Δ₋ (isol = 2). + +Knobs: `kmax` series order; `nx` cell count; `nq` Gauss–Lobatto order; `pfac` grid packing; +`cutoff` extension-cell span (cells nx−cutoff−1 … nx−1); `xfac` scale on the two inner matching radii; `tol_res` +resonant-cell quadrature tolerance. """ function solve_inner(::_BareGGJ{:galerkin}, params::GGJParameters, γ::Number; kwargs...) Δ, _ = _galerkin_solve(params, γ; kwargs...) diff --git a/src/InnerLayer/GGJ/InnerAsymptotics.jl b/src/InnerLayer/GGJ/InnerAsymptotics.jl index 7fa947160..8e07e0da4 100644 --- a/src/InnerLayer/GGJ/InnerAsymptotics.jl +++ b/src/InnerLayer/GGJ/InnerAsymptotics.jl @@ -3,10 +3,10 @@ # Wasow asymptotic basis ("inps" basis) for the GGJ inner-layer system. # # Reference: A. H. Glasser & Z. R. Wang, Phys. Plasmas 27, 012506 (2020) -# ("GW2020"), Sections II.A–II.G (Eqs. 3–55). Notation map (all equation +# ("GW2020"), Secs. II.A–II.G (Eqs. 1–53) and III (Eqs. 54–55). Notation map (all equation # numbers are GW2020): # -# A0/A1/A2 -> Eqs. 3–5 (physical-system coefficient matrices A = A₀+x⁻²A₁+x⁻⁴A₂) +# A0/A1/A2 -> Eqs. 3–5 (A = A₀+x⁻²A₁+x⁻⁴A₂ (Eq. 3); A₀, A₂ Eq. 4; A₁ Eq. 5) # T, Tinv -> Eqs. 6–8 (Jordan basis of A₀; u = Tv, v' = xJv, λ = Q^{-1/2}) # J0/J1/J2 -> Eqs. 9–10 (Jₖ = T^{-1} Aₖ T) # P_k, B_k -> Eqs. 11–24 (splitting transformation V = PW; Lyapunov solve Eq. 22) @@ -15,7 +15,7 @@ # Y0, R -> Eqs. 48–49 (lowest-order solution; Mercier Frobenius exponents r±) # Y_k, Z_k -> Eqs. 50–52 (Y-series Y = Y₀Z in shifted-exponent form) # U(x) -> Eq. 53 (final asymptotic solution U = TPQSY at large x) -# residual -> Eq. 54 (convergence measure Δ± used to pick x_max) +# residual -> Eq. 54 (convergence measure Δ±, used to pick the matching radius) using LinearAlgebra using StaticArrays @@ -27,7 +27,7 @@ Frozen `inps` Wasow asymptotic-basis construction for one `(GGJParameters, Q)` pair, stored as `SMatrix`/`SVector` for allocation-free evaluation. Index convention: `P[k+1]` holds the k-th-order matrix `P_k`, etc. -Fields: +## Fields - `params, Q, kmax` — input parameters and series truncation order. - `λ = 1/√Q` — complex scale factor used by the Wasow split. @@ -62,11 +62,7 @@ struct InnerAsymptoticsCache Z::Vector{SMatrix{2,2,ComplexF64,4}} # k = 0..kmax end -# ----------------------------------------------------------------------- -# Build T, Tinv, A_0..A_2, J_0..J_2. The coefficient matrices A₀,A₁,A₂ are -# GW2020 Eqs. (3)–(5); the Jordan basis T, T⁻¹ are Eqs. (7)–(8); λ = Q^{-1/2} -# (Eq. 6); and J_i = T⁻¹A_iT are Eqs. (9)–(10). -# ----------------------------------------------------------------------- +# T, T⁻¹, λ = Q^{-1/2} and J_i = T⁻¹A_iT from the coefficient matrices A₀–A₂ (GW2020 Eqs. 3–10). function _build_tjmat(p::GGJParameters, Q::ComplexF64) e = ComplexF64(p.E) @@ -78,8 +74,7 @@ function _build_tjmat(p::GGJParameters, Q::ComplexF64) q2 = q * q λ = 1 / sqrt(q) - # T (Eq. 7) — built by column-major reshape; the listing below is - # row-major Julia order matching that layout. + # T (Eq. 7) and T⁻¹ (Eq. 8), listed row by row. #! format: off T = @SMatrix ComplexF64[ 1 0 h*q q2/λ h*q -q2/λ @@ -100,7 +95,7 @@ function _build_tjmat(p::GGJParameters, Q::ComplexF64) ] #! format: on - # A_0, A_1, A_2 — GW2020 Eqs. (4), (5), and the A₂ matrix of Eq. (3). Build mutable then freeze. + # A₀ and A₂: GW2020 Eq. (4); A₁: Eq. (5). A0 = zeros(ComplexF64, 6, 6) A1 = zeros(ComplexF64, 6, 6) A2 = zeros(ComplexF64, 6, 6) @@ -132,7 +127,6 @@ function _build_tjmat(p::GGJParameters, Q::ComplexF64) A2[5, 1] = h / q2 A2[6, 1] = -h * k * q - # Freeze A_i and build J_i = T^{-1} A_i T. A0s = SMatrix{6,6,ComplexF64}(A0) A1s = SMatrix{6,6,ComplexF64}(A1) A2s = SMatrix{6,6,ComplexF64}(A2) @@ -144,18 +138,8 @@ function _build_tjmat(p::GGJParameters, Q::ComplexF64) return T, Tinv, (J0, J1, J2), λ end -# ----------------------------------------------------------------------- -# Closed-form Lyapunov solve for the splitting transformation — GW2020 Eq. (22), -# J₀²² P_k²¹ − P_k²¹ J₀¹¹ = −K_k²¹ and J₀¹¹ P_k¹² − P_k¹² J₀²² = −K_k¹², with the -# block-diagonal part B_k = K_k from Eq. (21). -# -# Given a 6×6 K, returns (B, P) such that: -# - B is block-diagonal with B[r1,r1] = K[r1,r1] and B[r2,r2] = K[r2,r2] -# - P has zero diagonal blocks, P[r1,r2] and P[r2,r1] given by the -# closed-form expressions below (which exploit the special structure -# of the lower-right block of J_0). -# ----------------------------------------------------------------------- - +# Closed-form solve of the GW2020 Eq. (22) Lyapunov equations for the off-diagonal blocks of P_k, +# using the structure of J₀'s lower-right block; B_k is the block-diagonal part of K_k (Eq. 21). function _lyap_solve(K::SMatrix{6,6,ComplexF64}, λ::ComplexF64) Bm = zeros(ComplexF64, 6, 6) Pm = zeros(ComplexF64, 6, 6) @@ -196,13 +180,7 @@ function _lyap_solve(K::SMatrix{6,6,ComplexF64}, λ::ComplexF64) return SMatrix{6,6,ComplexF64}(Bm), SMatrix{6,6,ComplexF64}(Pm) end -# ----------------------------------------------------------------------- -# Split recurrence — GW2020 Eqs. (14)–(19). Seeks descending power series -# J,P,B = Σ (·)_k x^{-2k} (Eq. 14) with B₀ = J₀, P₀ = I (Eq. 17), and solves the -# order-by-order recurrence Eq. (16)/(18) with K_k of Eq. (19) via the Lyapunov -# solve above. Builds B_k, P_k, K6_k for k = 0..kmax+2. -# ----------------------------------------------------------------------- - +# Splitting recurrence (GW2020 Eqs. 14–19): P_k, B_k, K_k for k = 0..kmax+2, each order by `_lyap_solve`. function _split_recurrence(J::NTuple{3,SMatrix{6,6,ComplexF64}}, λ::ComplexF64, kmax::Int) N = kmax + 3 # store k = 0..kmax+2 P = Vector{SMatrix{6,6,ComplexF64,36}}(undef, N) @@ -238,14 +216,8 @@ function _split_recurrence(J::NTuple{3,SMatrix{6,6,ComplexF64}}, λ::ComplexF64, return P, B, K6 end -# ----------------------------------------------------------------------- -# Coefs recurrence — the 2×2 reduced-equation construction, GW2020 Eqs. (25)–(52). -# Builds the inner-block diagonalization Q_k, C_k via K2_k (Eqs. 31–32, 36), -# the shearing matrices D_k (Eqs. 42–43), the lowest-order Y₀ and Mercier -# exponents r± (Eqs. 48–49), and the shifted-exponent series Y_k = Y₀Z_k with -# Z_k from Eqs. (50)–(52). -# ----------------------------------------------------------------------- - +# Reduced 2×2 construction (GW2020 Eqs. 25–52): Q_k, C_k via K2_k, shearing D_k, lowest-order Y₀ +# with exponents r±, and the series Y_k = Y₀Z_k. function _coefs(B::Vector{SMatrix{6,6,ComplexF64,36}}, R::SVector{2,Float64}, kmax::Int) @@ -272,12 +244,10 @@ function _coefs(B::Vector{SMatrix{6,6,ComplexF64,36}}, end K2[k+1] = K2acc - # Q_k = [[0, 0], [-K2[1,1], -K2[1,2]]] (column-major reshape gives this layout) Qm[k+1] = @SMatrix ComplexF64[ 0 0 -K2acc[1, 1] -K2acc[1, 2] ] - # C_k = [[0, 0], [K2[2,1], K2[1,1] + K2[2,2]]] Cm[k+1] = @SMatrix ComplexF64[ 0 0 K2acc[2, 1] K2acc[1, 1]+K2acc[2, 2] @@ -286,7 +256,6 @@ function _coefs(B::Vector{SMatrix{6,6,ComplexF64,36}}, # Build D_k for k = 0..kmax — GW2020 Eq. (43); c_2^21 = −(E+F+H+2) is Eq. (39). D = Vector{SMatrix{2,2,ComplexF64,4}}(undef, kmax + 1) - # D_0 = [[0, 1], [C_2[2,1], 3]] D[1] = @SMatrix ComplexF64[ 0 1 Cm[3][2, 1] 3 @@ -310,20 +279,17 @@ function _coefs(B::Vector{SMatrix{6,6,ComplexF64,36}}, r1 -1 ] - # E_k, Z_k, Y_k recurrence — GW2020 Eqs. (50)–(52): E_k = Y₀⁻¹D_kY₀ (Eq. 51), - # Z_k(R−2kI) − RZ_k = Σ E_l Z_{k−l} (Eq. 52), Y_k = Y₀Z_k (Eq. 50). + # Z_k and Y_k = Y₀Z_k from the GW2020 Eqs. (50)–(52) recurrence, with E_l = Y₀⁻¹D_lY₀ (Eq. 51). Y = Vector{SMatrix{2,2,ComplexF64,4}}(undef, kmax + 1) Z = Vector{SMatrix{2,2,ComplexF64,4}}(undef, kmax + 1) Z[1] = I2 Y[1] = Y0 for k in 1:kmax - # Build Z_k = sum_{l=1..k} E_l * Z_{k-l}, with E_l = Y0inv * D_l * Y0 Zacc = Z2 for l in 1:k El = Y0inv * D[l+1] * Y0 Zacc = Zacc + El * Z[k-l+1] end - # Divide each entry by (R[j] - R[i] - 2k) Zk = MMatrix{2,2,ComplexF64}(Zacc) for i in 1:2, j in 1:2 Zk[i, j] = Zk[i, j] / (R[j] - R[i] - 2 * k) @@ -335,10 +301,6 @@ function _coefs(B::Vector{SMatrix{6,6,ComplexF64,36}}, return K2, Qm, Cm, D, Y0, Y0inv, Y, Z end -# ----------------------------------------------------------------------- -# Public builder. -# ----------------------------------------------------------------------- - """ build_asymptotics(params::GGJParameters, Q::ComplexF64; kmax::Int=8) -> InnerAsymptoticsCache @@ -364,18 +326,8 @@ end build_asymptotics(params::GGJParameters, Q::Number; kmax::Int=8) = build_asymptotics(params, ComplexF64(Q); kmax=kmax) -# ----------------------------------------------------------------------- -# Horner evaluator with optional fractional-power prefactor. Sums the -# descending power series in x^{-2k} (GW2020 Eq. 14 form) for the Y, Q, and -# P[r2,r1] coefficient blocks, with the x^{R/2} Mercier prefactor. -# -# Computes y[i] = (Σ_{k=0..n} c[i,k] * x^k) * x^rvec[i] -# and dy[i] = d/dx of the above. -# -# `c` is an n_components × (n+1) matrix; the second axis is k = 0..n, -# 1-indexed in Julia. `x` may be real or complex (principal branch of x^rvec). -# ----------------------------------------------------------------------- - +# Horner sum y[i] = (Σ_{k=0..n} c[i,k+1] zᵏ)·z^rvec[i] and its z-derivative, z = 1/x² (GW2020 Eq. 14 form); +# rvec = −R/2 gives the x^R Mercier prefactor. c is n_components × (n+1); complex z uses the principal branch. function _horner(x::Number, c::AbstractMatrix{ComplexF64}; rvec::Union{Nothing,AbstractVector{<:Real}}=nothing, derivative::Bool=false) @@ -430,9 +382,7 @@ function _horner(x::Number, c::AbstractMatrix{ComplexF64}; return y, dy end -# Pack the cache's Y, Qmat, and the [r2, r1] block of P into the row-major -# reshape order used by `_horner`. Returned matrices are -# n_components × (kmax+1). +# Pack Y, and Qmat with P[3:6, 1:2], column-major into `_horner`'s n_components × (kmax+1) layout. function _pack_y_coefs(cache::InnerAsymptoticsCache) kmax = cache.kmax cc = Matrix{ComplexF64}(undef, 4, kmax + 1) @@ -487,10 +437,9 @@ Returns the 6×2 complex matrix `U` whose two columns are the power-like (Mercie the GGJ system (column 1 large, column 2 small), and (if `derivative=true`) the 6×2 matrix `dU` of their derivatives `dU/dx`. -If `apply_T=false`, the result is left in the J-rotated coordinate basis -(used by `asymptotic_residual` for residual checks). The default `apply_T=true` -returns the solutions in the original 6-component first-order-system -basis used by `_physical_uv` and the shooting / Galerkin solvers. +If `apply_T=false`, the result is left in the J-rotated basis (used by `asymptotic_residual`). +The default `apply_T=true` returns it in the GW2020 Eq. (2) state basis, which +[`physical_ua_dua`](@ref) converts to (Ψ, Ξ, Υ). """ function evaluate_asymptotics(cache::InnerAsymptoticsCache, x::Number; derivative::Bool=true, apply_T::Bool=true) @@ -584,17 +533,14 @@ function physical_ua_dua(cache::InnerAsymptoticsCache, x::Number) return ua, dua end -# ----------------------------------------------------------------------- -# Residual `delta` and adaptive xmax — the convergence measure Δ± of GW2020 -# Eq. (54), ‖u' − xJu‖/max(‖u'‖,‖xJu‖) in the J-rotated basis, used to choose -# x_max (GW2020 Sec. III, Fig. 3). -# ----------------------------------------------------------------------- +# Series residual, the analogue of GW2020 Eq. (54) for v' = xJv (Eq. 6), used to choose the matching +# radius (`pick_smax`, `_xmax_3level`; GW2020 Sec. III, Fig. 3). """ asymptotic_residual(cache::InnerAsymptoticsCache, x::Number) -> SVector{2,Float64} -Compute the convergence measure `Δ±` of the asymptotic basis at real or complex `x` for each -of the two algebraic columns (GW2020 Eq. 54). Returns +Convergence measure of the asymptotic basis at real or complex `x` for each of the two algebraic +columns, the analogue of GW2020 Eq. 54 in the J-rotated basis. Returns `‖dU − x·matrix·U‖∞ / max(‖dU‖∞, ‖x·matrix·U‖∞)` per column, where `matrix = J₀ + xfac·J₁ + xfac²·J₂` is the J-rotated coefficient matrix (the residual of `v' = xJv`, GW2020 Eq. 6). @@ -611,8 +557,6 @@ function asymptotic_residual(cache::InnerAsymptoticsCache, x::Number) M = M + xfac * xfac * cache.J[3] end - # matvec(:,:,1) = dU; matvec(:,:,2) = -x*M*U; matvec(:,:,0) = sum. - # delta(j) = ||matvec(:,j,0)||∞ / max(||matvec(:,j,1)||∞, ||matvec(:,j,2)||∞). matvec1 = dU matvec2 = -x * (M * U) matvec0 = matvec1 + matvec2 diff --git a/src/InnerLayer/GGJ/Ray.jl b/src/InnerLayer/GGJ/Ray.jl index 735b760de..6962cb61f 100644 --- a/src/InnerLayer/GGJ/Ray.jl +++ b/src/InnerLayer/GGJ/Ray.jl @@ -5,14 +5,12 @@ # decaying exponential pair, then the Galerkin.jl Hermite assembly solves [0, s_m] with # v(s_m) = Us + Δ·Ub + c₁E₁ + c₂E₂. Method and rationale: docs/src/inner_layer.md. -# GWP2016 Eq. 11 as dv/dx = M(x)·v in the plain state v = (Ψ, Ξ, Υ, Ψ', Ξ', Υ'). M is polynomial -# in x, so x = 0 is an ordinary point and the system continues analytically to complex x. - """ ode_matrix([CT,] p::GGJParameters, Q, x) -> SMatrix{6,6,CT} -Coefficient matrix `M(x)` of `dv/dx = M v`, `v = (Ψ, Ξ, Υ, Ψ', Ξ', Υ')`, for -real or complex `x`. `CT` selects the element type (default `ComplexF64`; +Coefficient matrix `M(x)` of GWP2016 Eq. 11 as `dv/dx = M v`, `v = (Ψ, Ξ, Υ, Ψ', Ξ', Υ')`, for +real or complex `x`. `M` is polynomial in `x`, so x = 0 is an ordinary point and the system +continues analytically to complex `x`. `CT` selects the element type (default `ComplexF64`; `Complex{Double64}` for the extended-precision march). """ ode_matrix(p::GGJParameters, Q::ComplexF64, x::Number) = @@ -146,12 +144,15 @@ function decaying_pair(params::GGJParameters, Q::ComplexF64, θ::Float64, S::Flo end """ - march_boundary(params, Q, θ, S, s_m, Us, Ub; rtol=1e-9, growth=30.0, seed=20260707) + march_boundary(params, Q, θ, S, s_m, Us, Ub; rtol=1e-9, ztrk=0.3, purge_budget=2.5, + growth=30.0, seed=20260707, dp_res=20.0) -> (Us_m, Ub_m, F) Transport the power-pair boundary data from the series radius `S` inward to `s_m` along the ray, modulo the decaying exponential pair (the quotient in which Δ is defined): 2-stage Radau IIA with purges against a carried decaying frame. +`rtol` sets the step factor c = (rtol/100)^{1/3}; `ztrk` caps resolved-band steps at ztrk/g_max; +`purge_budget` is the e-folds between purges; `growth`, `seed`, `dp_res` go to [`decaying_pair`](@ref). """ function march_boundary(params::GGJParameters, Q::ComplexF64, θ::Float64, S::Float64, s_m::Float64, Us::Vector{ComplexF64}, Ub::Vector{ComplexF64}; @@ -180,8 +181,8 @@ function march_boundary(params::GGJParameters, Q::ComplexF64, θ::Float64, return W + hc * ((CT(3) / 4) * @view(K[1:6, :]) + (CT(1) / 4) * @view(K[7:12, :])) end - # Damped-zone steps have cond ~ z ≫ 1; their structured LU backward error mixes u_small and u_big - # by ~eps·ρS²/2·‖u_big‖/‖u_small‖ (≈1e-4 at |Q| = 500 in Float64), so that zone runs in Double64. + # Damped-zone steps have cond ~ z ≫ 1; their structured LU backward error mixes u_small into u_big + # by ~eps·ρS²/2·‖u_big‖/‖u_small‖, so that zone runs in Double64. CTd = Complex{Double64} phd = CTd(cos(Double64(θ)), sin(Double64(θ))) 𝔐d(s) = phd * Matrix(ode_matrix(CTd, params, Q, phd * Double64(s))) @@ -268,11 +269,11 @@ function march_boundary(params::GGJParameters, Q::ComplexF64, θ::Float64, end """ - boundary_basis(params, Q, cache, θ, S; growth=30.0) + boundary_basis(params, Q, cache, θ, S; growth=30.0, seed=20260707, dp_res=20.0) -> (Us, Ub, E, cond_est) -Boundary data at s = S directly from the inps series (no march; used when -the series is already valid at the BVP edge): `Us`, `Ub` are the small/large +Boundary data at s = S taken directly from the inps series, used when the BVP edge is S itself +(s_m ≳ S): `Us`, `Ub` are the small/large power-like solutions as 6-component states in the inps normalization, `E` the numerically-generated decaying pair, `cond_est` the condition number of the column-normalized basis. @@ -323,14 +324,19 @@ end """ solve_ray(params::GGJParameters, Q; θ=angle(Q)/4, kmax=12, S=nothing, smax_tol=1e-9, - cfl=0.2, min_cells=1024, nq=6, verbose=false, kwargs...) -> RaySolveResult - -Solve the GGJ inner-layer problem on the rotated ray x = e^{iθ}s. -`Δ` is the rescaled pair (Δ₊, Δ₋) = (interchange, tearing), directly -comparable to the `:galerkin` backend. θ = 0 reproduces a real-axis solve; -`S` defaults to the inps series-residual radius (`pick_smax`); `cfl`, `min_cells` set the -Hermite grid ([`ray_breaks`](@ref)) and `nq` its quadrature; remaining keywords are march -knobs (see `march_boundary`, `decaying_pair`). + cfl=0.2, min_cells=1024, nq=6, verbose=false, …) -> RaySolveResult + +Solve the GGJ inner-layer problem on the rotated ray x = e^{iθ}s. `Δ` is the rescaled pair +(Δ₊, Δ₋) = (interchange, tearing), directly comparable to the `:galerkin` backend; θ = 0 is a +real-axis solve. + +Both boundary points are computed per solve. `S` defaults to the smallest radius where the series +residual is below `smax_tol` with order `kmax` ([`pick_smax`](@ref); it warns and uses the best +point if the tolerance is not reached). The BVP edge s_m is where every exponential family has +decayed 45 e-folds from the origin, from the local spectrum, scaled by `sm_fac`. `cfl`, +`min_cells` set the Hermite grid ([`ray_breaks`](@ref)) and `nq` its quadrature. `march_rtol` +is [`march_boundary`](@ref)'s `rtol`; `growth`, `seed`, `ztrk`, `purge_budget`, `dp_res` go to +`march_boundary`/[`decaying_pair`](@ref); `handoff` (diagnostic) supplies (Us, Ub) at S. """ function solve_ray(params::GGJParameters, Q::ComplexF64; θ::Float64=angle(Q) / 4, kmax::Int=12, @@ -485,7 +491,7 @@ end delta_convergence(params, Q; verbose=true, kwargs...) -> (; Δ, spread, base, table) Error bar for the matching data: re-solve with each numerical knob perturbed in turn (contour -angle, mesh, series order and radius, march tolerance, handoff radius, purification e-folds) and +angle, mesh, series order and radius, march tolerance, BVP edge s_m, decaying-pair separation) and report the relative change of (Δ₊, Δ₋); `spread` is the worst case per parity. θ moves outward only, away from the pseudo-resonance x² = −Q²(G+KF). """ diff --git a/src/InnerLayer/GGJ/Reference.jl b/src/InnerLayer/GGJ/Reference.jl index db5bfefde..13168d3d9 100644 --- a/src/InnerLayer/GGJ/Reference.jl +++ b/src/InnerLayer/GGJ/Reference.jl @@ -7,18 +7,12 @@ glasser_wang_2020_eq55(; taua=1.0, taur=1e6, v1=1.0) -> GGJParameters D-shaped aspect-ratio-2, q = 2 surface from Glasser & Wang, Phys. Plasmas -**27**, 012506 (2020), Eq. 55. This is the primary benchmark case for -validating the inps Wasow basis convergence (their Figs. 1–4). This is useful -only for benchmarking the galerkin solver and comparing to published results. +**27**, 012506 (2020), Eq. 55 (coefficients transcribed verbatim), the benchmark of their +inps Wasow-basis convergence study (Figs. 1–3). At its operating point `Q = 1.234e-1` +(Fig. 1) the GGJ backends are cross-checked against the Fortran `rmatch deltac`; the +paper's `Δ_±` (Eq. 54) is a series-convergence norm, not matching data. -The five coefficients below are transcribed verbatim from Eq. 55; the paper's -companion operating point is the scaled growth rate `Q = 1.234e-1` (their Fig. 1). -Note Eq. 55 does not tabulate an inner-region matching `Δ(Q)` — its `Δ_±` (Eq. 54) -is a convergence-error norm — so a quantitative `Δ(Q)` cross-check needs an -independent inner-layer reference, not this paper alone. - -Timescale parameters (taua, taur, v1) are set to canonical normalization; -callers should override them for physical cases. +`taua`, `taur`, `v1` default to a unit normalization; override them for physical cases. """ function glasser_wang_2020_eq55(; taua::Float64=1.0, taur::Float64=1e6, v1::Float64=1.0) return GGJParameters(; @@ -31,9 +25,8 @@ end q4_surface_benchmark() -> GGJParameters Physical q = 4 rational-surface benchmark point (S = τ_R/τ_A ≈ 4.58×10⁶, -D_I ≈ −0.31166, α = √(−D_I) ≈ 0.5583). Primary validation point for the -rotated-ray backend on the imaginary-Q axis (pinned at Q = 100i, 500i in -the test suite). +D_I ≈ −0.31166, p₁ = √(−D_I) ≈ 0.5583). Primary validation point for the +rotated-ray backend on the imaginary-Q axis (pinned at Q = 500i in the test suite). """ function q4_surface_benchmark() return GGJParameters(; diff --git a/src/InnerLayer/GGJ/Shooting.jl b/src/InnerLayer/GGJ/Shooting.jl index 8f36926d8..aebe029da 100644 --- a/src/InnerLayer/GGJ/Shooting.jl +++ b/src/InnerLayer/GGJ/Shooting.jl @@ -1,24 +1,12 @@ # Shooting.jl # -# Valid only for |Q| ≪ 1 (it underflows at large |γ|); the default GGJ backend is `:ray` -# (Ray.jl). Kept as a cheap model for tests and backend comparisons. -# -# Stable backward shooting solver for the GGJ inner-layer model. -# Integrates the 4×4 origin-diagonalized -# resistive-layer ODE from `tmax` (large-x asymptotic regime) backward to -# a small `tmin` (origin Frobenius regime), then projects onto the local -# Frobenius basis at the origin and reads off the parity-projected -# matching data. -# -# This solves the same inner-region equations as the Galerkin-based backends -# (GWP2016 Eq. 11 ≡ GW2020 Eq. 1) but by a different numerical method: a -# backward shoot in the origin-diagonalized basis rather than a weak form. The 4 origin Frobenius exponents are -# `al0 = (p1, 1/2, −p1, −1/2)` where `p1 = √(−D_I)` (Mercier-stable required; -# D_I = E+F+H−1/4, GWP2016 Eq. A9). The two "small" (singular) modes are -# columns 3 and 4 (`x^{−p1}` and `x^{−1/2}`); the two "large" (smooth) modes -# are columns 1 and 2 (`x^{p1}` and `x^{1/2}`). -# -# Reference: A. H. Glasser, Phys. Plasmas **23**, 072505 (2016). +# Backward shooting solver for the GGJ inner layer, valid only for |Q| ≪ 1 (the large-t initial +# condition underflows at large |Q|); used for tests and backend comparisons. It follows the Fourier- +# transform method of Glasser, Jardin & Tesauro, Phys. Fluids 27, 1225 (1984), Sec. V: the 4×4 system +# in the transform variable t is diagonalized at the origin (exponents `al0 = (p1, 1/2, −p1, −1/2)`, +# p1 = √(−D_I), GJT Eqs. 49, 56), integrated from `tmax` on the decaying large-t solutions back to +# `tmin`, projected onto the origin Frobenius basis, and Δ± read off from the coefficient ratios +# (GJT Eqs. 90–91). using LinearAlgebra using SpecialFunctions: gamma @@ -29,23 +17,35 @@ using OrdinaryDiffEq Precomputed origin- and infinity-side arrays for the backward shoot. Construct via [`_build_shooting_system`](@ref). + +## Fields + + - `params`, `Q` - Layer parameters and scaled growth rate. + - `p1`, `pplus` - p₁ = √(−D_I) and p₁ − 1/2. + - `al0` - Origin Frobenius exponents (p₁, 1/2, −p₁, −1/2), the diagonal of the origin exponent matrix. + - `al1` - First-order coupling in the origin-diagonalized basis. + - `d0`, `d0inv` - Origin diagonalizing matrix and its inverse. + - `ups` - `(4, 4, nps)` origin power-series coefficients in t², `ups[:, :, 1] = I`. + - `nps` - Origin series length. + - `d1` - Diagonalizing matrix at large t. + - `pexp` - Logarithmic exponents of the large-t asymptotic basis. + - `bl1` - Coefficients ±√Q of t²/2 in the large-t exponentials. + - `tmax`, `tmin` - Shoot start (large t) and end (small t). """ struct GGJShootingSystem params::GGJParameters Q::ComplexF64 p1::Float64 pplus::Float64 - # origin side - al0::SVector{4,Float64} # diagonal of origin exponent matrix - al1::SMatrix{4,4,ComplexF64,16} # first-order coupling (already in al0-diag basis) - d0::SMatrix{4,4,ComplexF64,16} # diagonalizing matrix at origin + al0::SVector{4,Float64} + al1::SMatrix{4,4,ComplexF64,16} + d0::SMatrix{4,4,ComplexF64,16} d0inv::SMatrix{4,4,ComplexF64,16} - ups::Array{ComplexF64,3} # (4, 4, nps) origin power-series coeffs + ups::Array{ComplexF64,3} nps::Int - # infinity side - d1::SMatrix{4,4,ComplexF64,16} # diagonalizing matrix at infinity - pexp::SVector{4,ComplexF64} # log-exponents of asymptotic basis - bl1::SVector{4,ComplexF64} # ±λ exponents of t² in asymptotic basis + d1::SMatrix{4,4,ComplexF64,16} + pexp::SVector{4,ComplexF64} + bl1::SVector{4,ComplexF64} tmax::Float64 tmin::Float64 end @@ -146,10 +146,7 @@ function _build_origin_arrays(p::GGJParameters, Q::ComplexF64; nps::Int=8, rtol: return (; al0, al1=al1_s, d0=d0_s, d0inv=d0inv_s, ups, nps, p1v, pplus, tmin) end -# ----------------------------------------------------------------------- -# Infinity arrays — large-t asymptotic basis. -# With nxps = 1 the higher-order vps recurrence is dead code; vps[:,:,1] = I. -# ----------------------------------------------------------------------- +# Large-t asymptotic basis, leading order only. function _build_infinity_arrays(p::GGJParameters, Q::ComplexF64, d0inv::SMatrix{4,4,ComplexF64}; @@ -214,7 +211,7 @@ function _build_infinity_arrays(p::GGJParameters, Q::ComplexF64, d1 = SMatrix{4,4,ComplexF64}(d1_m) bl1 = SVector{4,ComplexF64}(-lamda, -lamda, lamda, lamda) - # tmax (ntmax = 1 default). + # tmax: the smaller of the asymptotic-validity bound and 6/|Q|. p1v = sqrt(-mercier_di(p)) tmax_inner = sqrt((max(0.5, p1v)^2 - log(rtol)) / abs(lamda)) tmax_outer = 6.0 / abs(q) @@ -269,15 +266,7 @@ function _origin_basis(sys::GGJShootingSystem, t::Real) return SMatrix{4,4,ComplexF64}(u) end -# ----------------------------------------------------------------------- -# Initial condition at tmax. -# With nxps = 1, vps[:,:,1] = I, so the asymptotic-basis -# evaluator returns a diagonal v. The IC is then -# y(tmax) = d1 * v(:, 1:2) -# which extracts the first two columns of d1 scaled by the algebraic-mode -# exponential factors. This selects the two "small" decaying modes of the -# large-t asymptotic basis. -# ----------------------------------------------------------------------- +# Initial condition at tmax: the two decaying modes of the large-t basis, d1[:, 1:2]·exp(bl1·t²/2 + pexp·ln t). function _initial_condition(sys::GGJShootingSystem) t = sys.tmax @@ -342,9 +331,8 @@ end Solve the GGJ inner-layer matching problem by stable backward shooting in the origin-diagonalized 4×4 basis. -Returns an `InnerLayerResponse` with rescaling applied. `_delta_from_c0` returns the -pair (Δ₊, Δ₋) = (interchange, tearing): even and odd parity of the displacement Ξ -(Ψ odd and even), the same order as the other GGJ backends. +Returns an `InnerLayerResponse` rescaled by [`rescale_delta`](@ref), with `interchange` = Δ₊ +(Ξ even) and `tearing` = Δ₋ (Ξ odd), the same convention as the other GGJ backends. Tolerances `reltol`/`abstol` are the integrator tolerances; `rtol_origin` controls the truncation error of the origin Frobenius series and the diff --git a/src/InnerLayer/InnerLayerInterface.jl b/src/InnerLayer/InnerLayerInterface.jl index 03ca65d76..227b066bc 100644 --- a/src/InnerLayer/InnerLayerInterface.jl +++ b/src/InnerLayer/InnerLayerInterface.jl @@ -1,7 +1,7 @@ # InnerLayerInterface.jl # -# Abstract interface for resistive inner-layer models. Concrete models -# (e.g. GGJ, SLAYER, kinetic) live in submodules and specialize `solve_inner`. +# Abstract interface for resistive inner-layer models. Concrete models (GGJ, SLAYER) live in +# submodules and specialize `solve_inner`. """ InnerLayerModel @@ -35,25 +35,16 @@ the `Δ_{j,±}(γ)` of Glasser, Wang & Park, Phys. Plasmas **23**, 112506 # Fields - - `tearing` — the **odd-parity** matching coefficient Δ₋ (GWP2016 Eq. 34; Pletzer, - Bondeson & Dewar, J. Comput. Phys. 115, 530 (1994), Eqs. 87–89). Corresponds to a - flux perturbation W that is EVEN in x and a displacement/velocity/temperature - perturbation that is ODD — i.e., the - reconnecting mode with a current sheet at the rational surface. This is - the tearing drive that appears as Δ' in the classical constant-ψ - tearing equation. Must be populated by every resistive inner-layer model. - - - `interchange` — the **even-parity** matching coefficient Δ₊. Corresponds to W odd, - N and Θ even — i.e., the - non-reconnecting interchange/ballooning channel. Its dissipative piece - in toroidal geometry is the Glasser, Greene & Johnson stabilization - term that opposes tearing growth (Glasser, Greene & Johnson 1975; - Lütjens-Bondeson-Roy 1993). Pressureless inner-layer models (e.g. - SLAYER's Fitzpatrick Riccati) set this identically zero. - -Parity labels follow GWP2016 and Pletzer, Bondeson & Dewar: the parity of the -displacement (Ξ, matched to the outer ξ), with + even and − odd. The fields are named -by the physics channel because the parity of the flux W is the opposite. Positional + - `tearing` — odd-parity matching coefficient Δ₋: Ξ odd, Ψ even, the reconnecting channel + whose Δ is the constant-ψ tearing Δ′ (Pletzer, Bondeson & Dewar, J. Comput. Phys. 115, 530 + (1994), Eqs. 77, 86–87, 89). Every resistive inner-layer model populates it. + - `interchange` — even-parity matching coefficient Δ₊: Ξ even, Ψ odd, the non-reconnecting + interchange channel carrying the Glasser, Greene & Johnson (1975) stabilization. + Pressureless models (SLAYER) set it to zero. + +Parity is that of the displacement Ξ, matched to the outer ξ (GWP2016 Eq. 34; Pletzer, +Bondeson & Dewar Eqs. 32–33), with + even and − odd. The fields are named by the physics +channel because the parity of the flux Ψ is the opposite. Positional pairs elsewhere in `InnerLayer` (e.g. the `Δ` of [`solve_inner_profile`](@ref)) are ordered (Δ₊, Δ₋) = (interchange, tearing). """ @@ -68,13 +59,14 @@ InnerLayerResponse(; tearing::Number=0, interchange::Number=0) = """ solve_inner(model::InnerLayerModel, params, γ::Number; kwargs...) -> InnerLayerResponse -Compute the parity-projected matching data `(Δ_tearing, Δ_interchange)` for +Compute the parity-projected matching data (the `tearing` and `interchange` fields of +`InnerLayerResponse`) for the given inner-layer `model`, physical parameters `params`, and complex growth rate `γ`. Concrete models specialize this function. See `InnerLayerResponse` for the physics-oriented field definitions. Pressureless models (SLAYER) populate only `tearing` and leave -`interchange` at zero; two-fluid / finite-β models (GGJ) populate both. +`interchange` at zero; finite-pressure models (GGJ) populate both. """ function solve_inner end diff --git a/src/Tearing/Dispersion/CoupledFullMatch.jl b/src/Tearing/Dispersion/CoupledFullMatch.jl index 6a4362d6f..223656518 100644 --- a/src/Tearing/Dispersion/CoupledFullMatch.jl +++ b/src/Tearing/Dispersion/CoupledFullMatch.jl @@ -4,7 +4,7 @@ # the m inner-layer resonances decoupled via the matching-identity rows # # C^j_L = d^j_+ − d^j_- -# C^j_R = -(d^j_+ + d^j_-) +# C^j_R = d^j_+ + d^j_- # # (see Wang-Glasser-Brennan-Liu-Park 2020, Phys. Plasmas **27**, 122503, # Eq. (11a)-(11d) and Glasser-Wang-Park 2016, Phys. Plasmas **23**, 112506, @@ -195,15 +195,15 @@ function (mc::MultiSurfaceCouplingFull)(Q::Number) # --- Upper-right 2×2 block: matching identity --- # C^k_L = d^k_+ − d^k_- ⇒ mat[idx1,idx3]=-1, mat[idx1,idx4]=+1 - # C^k_R = -(d^k_+ + d^k_-) ⇒ mat[idx2,idx3]=-1, mat[idx2,idx4]=-1 + # C^k_R = d^k_+ + d^k_- ⇒ mat[idx2,idx3]=-1, mat[idx2,idx4]=-1 mat[idx1, idx3] = -1 mat[idx1, idx4] = 1 mat[idx2, idx3] = -1 mat[idx2, idx4] = -1 # --- Lower-right 2×2 block: inner Δ matching --- - # d^k_+ eqn: -Δ_int·d^k_+ + Δ_tear·d^k_- + (outer D' terms) = 0 - # d^k_- eqn: -Δ_int·d^k_+ - Δ_tear·d^k_- + (outer D' terms) = 0 + # L-side row: -Δ_int·d^k_+ + Δ_tear·d^k_- + (outer D' terms) = 0 (GWP2016 Eq. 37) + # R-side row: -Δ_int·d^k_+ - Δ_tear·d^k_- + (outer D' terms) = 0 mat[idx3, idx3] = -delta1 mat[idx3, idx4] = delta2 mat[idx4, idx3] = -delta1 diff --git a/src/Tearing/Runner/run_slayer.jl b/src/Tearing/Runner/run_slayer.jl index 49a1af866..93f67163c 100644 --- a/src/Tearing/Runner/run_slayer.jl +++ b/src/Tearing/Runner/run_slayer.jl @@ -178,7 +178,7 @@ the `S^(1/3)` Δ(Q) scale, both built on r_s). Near surface `k` the outer solution combines the large and small Frobenius solutions with the Mercier exponent `α = √(−D_I)`, `D_I = E + F + H − 1/4` -(Glasser, Greene & Johnson 1975, Eq. 48; STRIDE's `alpha`). The displacement +(Glasser, Greene & Johnson 1975, Eqs. 16, 24; STRIDE's `alpha`). The displacement scales as `|x|^(−1/2 ± α)` (Glasser, Wang & Park 2016, Eq. 26), so the flux-like variable `ψ ∝ x·ξ` of the slab Δ' definition scales as `A_L·|x|^(1/2−α) + A_S·|x|^(1/2+α)`. Rescaling the radial variable From e1371f4d123c1aa726d84717319cd51806144019 Mon Sep 17 00:00:00 2001 From: Matthew Pharr Date: Mon, 19 Oct 2026 15:36:26 +0200 Subject: [PATCH 07/12] InnerLayer - MINOR - Format the files changed by the GGJ ray refactor --- src/ForceFreeStates/Matching/MatchProblem.jl | 20 ++++++++++++------- src/ForceFreeStates/Matching/ResonantMatch.jl | 1 + src/InnerLayer/GGJ/Galerkin.jl | 2 +- src/InnerLayer/GGJ/Ray.jl | 2 +- src/InnerLayer/InnerLayerInterface.jl | 10 +++++----- src/InnerLayer/SLAYER/LayerInputs.jl | 17 +++++++++++++--- src/Tearing/Dispersion/CoupledFullMatch.jl | 2 +- 7 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/ForceFreeStates/Matching/MatchProblem.jl b/src/ForceFreeStates/Matching/MatchProblem.jl index 47e7835ae..3d7cf9188 100644 --- a/src/ForceFreeStates/Matching/MatchProblem.jl +++ b/src/ForceFreeStates/Matching/MatchProblem.jl @@ -12,13 +12,15 @@ field `bpen`. `ffs` needs the Δ′ coil block, from `Galerkin(; rpec_flag=true) with `vac_flag=true`. # Keywords -- `eta`, `rho`, `rotation`: resistivity in Ω·m, mass density in kg/m³ and rotation frequency - in Hz, a scalar for every surface or one value per `ffs.surfaces` entry (core to edge). - Required unless `ideal=true`. -- `gamma`: ratio of specific heats. -- `ideal`: skip the inner layer and return the perfectly shielding solution. + + - `eta`, `rho`, `rotation`: resistivity in Ω·m, mass density in kg/m³ and rotation frequency + in Hz, a scalar for every surface or one value per `ffs.surfaces` entry (core to edge). + Required unless `ideal=true`. + - `gamma`: ratio of specific heats. + - `ideal`: skip the inner layer and return the perfectly shielding solution. ## Fields + - `ffs` - The outer solve being matched; held by reference, not copied. - `eta`, `rho`, `rotation` - Per-surface η in Ω·m, ρ in kg/m³ and rotation frequency in Hz, following `ffs.surfaces`. - `gamma` - Ratio of specific heats. @@ -185,7 +187,9 @@ function _compute_match(prob::MatchProblem, model::InnerLayer.GGJModel) if gal_sol === nothing xi = Array{ComplexF64,3}(undef, 0, 0, 0) xi_deriv = Array{ComplexF64,3}(undef, 0, 0, 0) - empty!(inner_psi); empty!(inner_xi); empty!(inner_b) + empty!(inner_psi); + empty!(inner_xi); + empty!(inner_b) else sols = gal_sol.xi # (mpert, ngrid, nsol) sols_deriv = gal_sol.xi_deriv @@ -209,7 +213,9 @@ function _compute_match(prob::MatchProblem, model::InnerLayer.GGJModel) if isempty(sols_cut) @warn "MatchProblem: the solve retained no cut solution (set cut_solution=true on Galerkin), " * "so the composite inner-region profiles are skipped; bpen and the matched outer ξ are unaffected" maxlog=1 - empty!(inner_psi); empty!(inner_xi); empty!(inner_b) + empty!(inner_psi); + empty!(inner_xi); + empty!(inner_b) else cut_range = gal_sol.cut_range keep = .!gal_sol.issing diff --git a/src/ForceFreeStates/Matching/ResonantMatch.jl b/src/ForceFreeStates/Matching/ResonantMatch.jl index 0b3e6e882..8fc93cf65 100644 --- a/src/ForceFreeStates/Matching/ResonantMatch.jl +++ b/src/ForceFreeStates/Matching/ResonantMatch.jl @@ -9,6 +9,7 @@ Matching coefficients and matched profiles, found in `result.match`. The profile fields are empty when the solve kept no Galerkin basis; the inner fields are empty with `ideal`. ## Fields + - `cout`, `cin`: `(2msing, ncoil)` outer and inner coefficients. - `deltar`: `(msing, 2)` inner-layer Δ per surface, columns (Δ₊, Δ₋) = (interchange, tearing). - `rpec_eig`: forced eigenvalue γ = 2πi·n·f per surface. diff --git a/src/InnerLayer/GGJ/Galerkin.jl b/src/InnerLayer/GGJ/Galerkin.jl index 552177c65..10fe8c052 100644 --- a/src/InnerLayer/GGJ/Galerkin.jl +++ b/src/InnerLayer/GGJ/Galerkin.jl @@ -649,7 +649,7 @@ function _parity_bcs_and_solve!(ws::GalerkinWorkspace, params::GGJParameters, Q: if i > ws.ndim continue end - for jj in max(1, i - ws.kl):min(ws.ndim, i + ws.kl) + for jj in max(1, i-ws.kl):min(ws.ndim, i+ws.kl) ws.mat[offset+i-jj, jj, isol] = 0 end end diff --git a/src/InnerLayer/GGJ/Ray.jl b/src/InnerLayer/GGJ/Ray.jl index 6962cb61f..ee95cac2f 100644 --- a/src/InnerLayer/GGJ/Ray.jl +++ b/src/InnerLayer/GGJ/Ray.jl @@ -499,7 +499,7 @@ function delta_convergence(params::GGJParameters, Q::ComplexF64; verbose::Bool=t base = solve_ray(params, Q; kwargs...) variations = [ ("θ → 1.2θ", (; θ=(base.θ == 0 ? 0.1 : 1.2 * base.θ))), - ("mesh ×2", (; cfl=base.cfl / 2, min_cells=2 * base.min_cells)), + ("mesh ×2", (; cfl=(base.cfl / 2), min_cells=2 * base.min_cells)), ("kmax+4, S↑", (; kmax=16, smax_tol=1e-10)), ("march_rtol/100", (; march_rtol=1e-11)), ("sm_fac 1→1.4", (; sm_fac=1.4)), diff --git a/src/InnerLayer/InnerLayerInterface.jl b/src/InnerLayer/InnerLayerInterface.jl index 227b066bc..86885d993 100644 --- a/src/InnerLayer/InnerLayerInterface.jl +++ b/src/InnerLayer/InnerLayerInterface.jl @@ -80,15 +80,15 @@ needs from the layer, so drivers never touch model internals. Returns a named tuple with at least: - `Δ` — the same matching data as [`solve_inner`](@ref), as the pair - (Δ₊, Δ₋) = (interchange, tearing) + (Δ₊, Δ₋) = (interchange, tearing) - `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 in the order of `Δ`, 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 e909e68b1..7e7fb4175 100644 --- a/src/InnerLayer/SLAYER/LayerInputs.jl +++ b/src/InnerLayer/SLAYER/LayerInputs.jl @@ -183,12 +183,16 @@ 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. Scalar or a callable of `psi`, evaluated per surface (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`, `:fitzpatrick`, `:toroidal`). When `nothing` (default), Julia @@ -203,6 +207,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 @@ -210,21 +215,26 @@ profiles, without an intermediate file round-trip. doesn't currently expose. Pass a scalar / vector / callable to use a prescribed value. (For `dc_type=:fitzpatrick` and `:lar`, dgeo_val is not consulted.) + - `dc_type` -- `:none` (default), `:lar`, `:fitzpatrick`, or `:toroidal`. + - `rs_method` -- radial label defining `r_s` for the whole layer stack: `:midplane` (default), `:halfwidth`, `:fsa`, `:volume`, or `:flux`. See [`radial_label`](@ref) for the definitions. S, the r-based shear, W_d, and the Δ' reference-length factor `k_ref` all follow the choice together, so every option is self-consistent. Not exposed via TOML — programmatic use only. + - `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). @@ -370,9 +380,10 @@ function build_slayer_inputs(equil, sings, profiles::KineticProfiles; 1.0 end alpha_k = if rg === nothing - @warn("build_slayer_inputs: sing.restype not populated; using the " * - "slab Mercier exponent α = 1/2 for the Δ' reference-length " * - "conversion at all such surfaces.", maxlog=1) + @warn( + "build_slayer_inputs: sing.restype not populated; using the " * + "slab Mercier exponent α = 1/2 for the Δ' reference-length " * + "conversion at all such surfaces.", maxlog=1) 0.5 else sqrt(max(-(rg.E + rg.F + rg.H - 0.25), 0.0)) diff --git a/src/Tearing/Dispersion/CoupledFullMatch.jl b/src/Tearing/Dispersion/CoupledFullMatch.jl index 223656518..3ae55d515 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 From c8b68e4ba95c461ca5052b26cfa6b16edc4ea01f Mon Sep 17 00:00:00 2001 From: Matthew Pharr Date: Tue, 20 Oct 2026 09:23:05 +0200 Subject: [PATCH 08/12] InnerLayer - API! - Drop unread asymptotic-cache fields and un-export GGJ internals --- .../inner_layer/make_backend_regime_map.jl | 2 +- .../make_convergence_Sinvariance.jl | 2 +- .../inner_layer/make_rotated_ray_contour.jl | 2 +- .../inner_layer/make_solution_profiles.jl | 2 +- docs/src/inner_layer.md | 6 +- regression-harness/src/runner.jl | 4 +- src/InnerLayer/GGJ/GGJ.jl | 6 +- src/InnerLayer/GGJ/InnerAsymptotics.jl | 56 ++++++------------- src/InnerLayer/InnerLayer.jl | 12 +--- test/runtests_dispersion_coupled.jl | 1 + test/runtests_dispersion_residual.jl | 1 + test/runtests_innerlayer.jl | 10 ++-- test/runtests_matching_models.jl | 2 +- 13 files changed, 39 insertions(+), 67 deletions(-) diff --git a/docs/src/figures/inner_layer/make_backend_regime_map.jl b/docs/src/figures/inner_layer/make_backend_regime_map.jl index 163b50493..f0978ab30 100644 --- a/docs/src/figures/inner_layer/make_backend_regime_map.jl +++ b/docs/src/figures/inner_layer/make_backend_regime_map.jl @@ -19,7 +19,7 @@ using Printf const IL = GeneralizedPerturbedEquilibrium.InnerLayer const GGJ = IL.GGJ -p = IL.q4_surface_benchmark() +p = IL.GGJ.q4_surface_benchmark() γ(aq) = im * aq * GGJ.q0(p) # imaginary axis: Q = i|Q| # Worst-case relative error over the two parity components vs the :ray reference. diff --git a/docs/src/figures/inner_layer/make_convergence_Sinvariance.jl b/docs/src/figures/inner_layer/make_convergence_Sinvariance.jl index ec8b1a4f1..2b4129baf 100644 --- a/docs/src/figures/inner_layer/make_convergence_Sinvariance.jl +++ b/docs/src/figures/inner_layer/make_convergence_Sinvariance.jl @@ -16,7 +16,7 @@ using Printf const IL = GeneralizedPerturbedEquilibrium.InnerLayer -p = IL.q4_surface_benchmark() +p = IL.GGJ.q4_surface_benchmark() Q = 500.0im conv = IL.delta_convergence(p, Q; verbose=false) diff --git a/docs/src/figures/inner_layer/make_rotated_ray_contour.jl b/docs/src/figures/inner_layer/make_rotated_ray_contour.jl index 15abe1670..a23c39fba 100644 --- a/docs/src/figures/inner_layer/make_rotated_ray_contour.jl +++ b/docs/src/figures/inner_layer/make_rotated_ray_contour.jl @@ -19,7 +19,7 @@ const GGJ = IL.GGJ # q = 4 rational-surface benchmark on the imaginary-Q axis (the regime that # defeats :galerkin). Q is the scaled growth rate; θ makes the parabolic # exponent real. -p = IL.q4_surface_benchmark() +p = IL.GGJ.q4_surface_benchmark() Q = 500.0im θ = angle(Q) / 4 # = π/8 = 22.5° diff --git a/docs/src/figures/inner_layer/make_solution_profiles.jl b/docs/src/figures/inner_layer/make_solution_profiles.jl index 6725c0241..cf3043589 100644 --- a/docs/src/figures/inner_layer/make_solution_profiles.jl +++ b/docs/src/figures/inner_layer/make_solution_profiles.jl @@ -16,7 +16,7 @@ using Printf const IL = GeneralizedPerturbedEquilibrium.InnerLayer const GGJ = IL.GGJ -p = IL.q4_surface_benchmark() +p = IL.GGJ.q4_surface_benchmark() Q = 2.0im # imaginary axis, beyond the |Q|≪1 shooting regime, # small enough that the BVP domain reaches # the series radius directly (no march) — so the diff --git a/docs/src/inner_layer.md b/docs/src/inner_layer.md index 8c30cf7ce..2912528ff 100644 --- a/docs/src/inner_layer.md +++ b/docs/src/inner_layer.md @@ -54,7 +54,7 @@ unknowns ``d_\pm`` of GWP2016 Eq. (38) and Pletzer, Bondeson & Dewar Eqs. 83, 85 !!! note "Benchmark surface used in the figures" The figures use the ``q = 4`` DIII-D-like surface of - [`q4_surface_benchmark`](@ref InnerLayer.q4_surface_benchmark) + [`q4_surface_benchmark`](@ref InnerLayer.GGJ.q4_surface_benchmark) (``S \approx 4.6\times10^{6}``, ``D_I \approx -0.31``). ### Solver backends @@ -146,7 +146,7 @@ This point sits near a pole of ``\Delta_+(Q)``, which amplifies every solver's e ``1.3\times10^{-4}`` `:galerkin`↔`:ray` difference in ``\Delta_+`` against ``4\times10^{-7}`` in ``\Delta_-``. **Physical benchmark on the imaginary axis.** On the ``q=4`` rational-surface -benchmark ([`q4_surface_benchmark`](@ref InnerLayer.q4_surface_benchmark), ``S \approx 4.58\times10^6``, +benchmark ([`q4_surface_benchmark`](@ref InnerLayer.GGJ.q4_surface_benchmark), ``S \approx 4.58\times10^6``, ``D_I \approx -0.312``) the `:ray` backend is pinned at ``Q = 500i``, a regime entirely beyond `:galerkin`: @@ -190,7 +190,7 @@ when supplying the Galerkin `nx`/`xfac` knobs; passing them to `:ray` throws a ` ```julia using GeneralizedPerturbedEquilibrium.InnerLayer -p = q4_surface_benchmark() # GGJParameters for the q=4 benchmark surface +p = GGJ.q4_surface_benchmark() # GGJParameters for the q=4 benchmark surface γ = 500im * GGJ.q0(p) # physical rate placing Q on the imaginary axis at 500i Δ = solve_inner(GGJModel(), p, γ) # Δ.interchange, Δ.tearing with the default :ray backend diff --git a/regression-harness/src/runner.jl b/regression-harness/src/runner.jl index b9e4432e5..2e7ec5415 100644 --- a/regression-harness/src/runner.jl +++ b/regression-harness/src/runner.jl @@ -110,7 +110,7 @@ using GeneralizedPerturbedEquilibrium using GeneralizedPerturbedEquilibrium.InnerLayer using HDF5 γ = 2π * 1e3 * im -p = glasser_wang_2020_eq55(; taua=2.11226e-7, taur=0.968219) +p = InnerLayer.GGJ.glasser_wang_2020_eq55(; taua=2.11226e-7, taur=0.968219) t_start = time() Δ = solve_inner(GGJModel(solver=:galerkin), p, γ) elapsed = time() - t_start @@ -133,7 +133,7 @@ using Pkg using GeneralizedPerturbedEquilibrium using GeneralizedPerturbedEquilibrium.InnerLayer using HDF5 -p = q4_surface_benchmark() +p = InnerLayer.GGJ.q4_surface_benchmark() γ = 500.0im * InnerLayer.GGJ.q0(p) t_start = time() Δ = solve_inner(GGJModel(solver=:ray), p, γ) diff --git a/src/InnerLayer/GGJ/GGJ.jl b/src/InnerLayer/GGJ/GGJ.jl index eff0f68d9..fcb299164 100644 --- a/src/InnerLayer/GGJ/GGJ.jl +++ b/src/InnerLayer/GGJ/GGJ.jl @@ -77,10 +77,6 @@ include("Ray.jl") export GGJModel, GGJParameters export mercier_di, mercier_dr, inner_Q, rescale_delta -export build_asymptotics, evaluate_asymptotics -export InnerAsymptoticsCache -export glasser_wang_2020_eq55 -export solve_ray, RaySolveResult, pick_smax, physical_ua_dua -export delta_convergence, solution_profile, asymptotic_profile, q4_surface_benchmark +export solve_ray, pick_smax, delta_convergence, solution_profile, asymptotic_profile end # module GGJ diff --git a/src/InnerLayer/GGJ/InnerAsymptotics.jl b/src/InnerLayer/GGJ/InnerAsymptotics.jl index 8e07e0da4..3abcaced9 100644 --- a/src/InnerLayer/GGJ/InnerAsymptotics.jl +++ b/src/InnerLayer/GGJ/InnerAsymptotics.jl @@ -30,36 +30,23 @@ convention: `P[k+1]` holds the k-th-order matrix `P_k`, etc. ## Fields - `params, Q, kmax` — input parameters and series truncation order. - - `λ = 1/√Q` — complex scale factor used by the Wasow split. - `R = (r₊, r₋)` — Mercier-shifted Frobenius exponents at infinity (Eq. 49). - - `T, Tinv` — 6×6 eigenvector basis of A₀ (Eq. 7–8). - - `J` — `(J₀, J₁, J₂)`, the J-rotated coefficient matrices (Eq. 9–10). - - `P, B` — splitting matrices, k = 0..kmax+2 (Eqs. 16, 22). - - `K2` — 2×2 inner working matrices, k = 0..kmax+2 (Eq. 32; entry k=0 unused). - - `Qmat, Cmat` — 2×2 inner-block transformation matrices, k = 0..kmax+2 (Eqs. 32–39). - - `Dmat` — 2×2 shearing matrices, k = 0..kmax (Eq. 43). - - `Y0, Y0inv` — lowest-order Y matrix and its inverse (Eq. 48; exponents from Eq. 49). - - `Y, Z` — 2×2 series matrices, k = 0..kmax (Eq. 52). + - `T` — 6×6 eigenvector basis of A₀ (Eq. 7). + - `J` — `(J₀, J₁, J₂)`, the J-rotated coefficient matrices (Eqs. 9–10). + - `P` — splitting matrices, k = 0..kmax+2 (Eqs. 16, 22). + - `Qmat` — 2×2 inner-block transformation matrices, k = 0..kmax+2 (Eqs. 32–39). + - `Y` — 2×2 series matrices Y_k = Y₀Z_k, k = 0..kmax (Eqs. 50–52). """ struct InnerAsymptoticsCache params::GGJParameters Q::ComplexF64 kmax::Int - λ::ComplexF64 R::SVector{2,Float64} T::SMatrix{6,6,ComplexF64,36} - Tinv::SMatrix{6,6,ComplexF64,36} J::NTuple{3,SMatrix{6,6,ComplexF64,36}} - P::Vector{SMatrix{6,6,ComplexF64,36}} # k = 0..kmax+2 - B::Vector{SMatrix{6,6,ComplexF64,36}} # k = 0..kmax+2 - K2::Vector{SMatrix{2,2,ComplexF64,4}} # k = 0..kmax+2 - Qmat::Vector{SMatrix{2,2,ComplexF64,4}} # k = 0..kmax+2 - Cmat::Vector{SMatrix{2,2,ComplexF64,4}} # k = 0..kmax+2 - Dmat::Vector{SMatrix{2,2,ComplexF64,4}} # k = 0..kmax - Y0::SMatrix{2,2,ComplexF64,4} - Y0inv::SMatrix{2,2,ComplexF64,4} - Y::Vector{SMatrix{2,2,ComplexF64,4}} # k = 0..kmax - Z::Vector{SMatrix{2,2,ComplexF64,4}} # k = 0..kmax + P::Vector{SMatrix{6,6,ComplexF64,36}} + Qmat::Vector{SMatrix{2,2,ComplexF64,4}} + Y::Vector{SMatrix{2,2,ComplexF64,4}} end # T, T⁻¹, λ = Q^{-1/2} and J_i = T⁻¹A_iT from the coefficient matrices A₀–A₂ (GW2020 Eqs. 3–10). @@ -135,7 +122,7 @@ function _build_tjmat(p::GGJParameters, Q::ComplexF64) J1 = Tinv * A1s * T J2 = Tinv * A2s * T - return T, Tinv, (J0, J1, J2), λ + return T, (J0, J1, J2), λ end # Closed-form solve of the GW2020 Eq. (22) Lyapunov equations for the off-diagonal blocks of P_k, @@ -180,21 +167,19 @@ function _lyap_solve(K::SMatrix{6,6,ComplexF64}, λ::ComplexF64) return SMatrix{6,6,ComplexF64}(Bm), SMatrix{6,6,ComplexF64}(Pm) end -# Splitting recurrence (GW2020 Eqs. 14–19): P_k, B_k, K_k for k = 0..kmax+2, each order by `_lyap_solve`. +# Splitting recurrence (GW2020 Eqs. 14–19): P_k, B_k for k = 0..kmax+2, each order by `_lyap_solve` of K_k. function _split_recurrence(J::NTuple{3,SMatrix{6,6,ComplexF64}}, λ::ComplexF64, kmax::Int) N = kmax + 3 # store k = 0..kmax+2 P = Vector{SMatrix{6,6,ComplexF64,36}}(undef, N) B = Vector{SMatrix{6,6,ComplexF64,36}}(undef, N) - K6 = Vector{SMatrix{6,6,ComplexF64,36}}(undef, N) Z6 = zero(SMatrix{6,6,ComplexF64}) P[1] = SMatrix{6,6,ComplexF64}(I) # P_0 = I B[1] = J[1] # B_0 = J_0 - K6[1] = J[1] for k in 1:(kmax+2) - kk = k + 1 # 1-based slot for K6/B/P at index k - # K6_k starts as J_k (only k = 1, 2 contribute), else 0 + kk = k + 1 # 1-based slot for B/P at index k + # K_k starts as J_k (only k = 1, 2 contribute), else 0 Kacc = (k <= 2) ? J[k+1] : Z6 # +2*(k-1)*P_{k-1} (k > 1 only) if k > 1 @@ -208,12 +193,11 @@ function _split_recurrence(J::NTuple{3,SMatrix{6,6,ComplexF64}}, λ::ComplexF64, end Kacc = Kacc - P[l+1] * B[kml+1] end - K6[kk] = Kacc Bk, Pk = _lyap_solve(Kacc, λ) B[kk] = Bk P[kk] = Pk end - return P, B, K6 + return P, B end # Reduced 2×2 construction (GW2020 Eqs. 25–52): Q_k, C_k via K2_k, shearing D_k, lowest-order Y₀ @@ -298,7 +282,7 @@ function _coefs(B::Vector{SMatrix{6,6,ComplexF64,36}}, Y[k+1] = Y0 * Z[k+1] end - return K2, Qm, Cm, D, Y0, Y0inv, Y, Z + return Qm, Y end """ @@ -313,14 +297,10 @@ function build_asymptotics(params::GGJParameters, Q::ComplexF64; kmax::Int=8) # Mercier Frobenius exponents r± = 3/2 ± √(−D_I) — GW2020 Eq. (49). R = SVector{2,Float64}(p1v + 1.5, -p1v + 1.5) - T, Tinv, J, λ = _build_tjmat(params, Q) - P, B, _ = _split_recurrence(J, λ, kmax) - K2, Qm, Cm, D, Y0, Y0inv, Y, Z = _coefs(B, R, kmax) - - return InnerAsymptoticsCache( - params, Q, kmax, λ, R, T, Tinv, J, - P, B, K2, Qm, Cm, D, Y0, Y0inv, Y, Z - ) + T, J, λ = _build_tjmat(params, Q) + P, B = _split_recurrence(J, λ, kmax) + Qm, Y = _coefs(B, R, kmax) + return InnerAsymptoticsCache(params, Q, kmax, R, T, J, P, Qm, Y) end build_asymptotics(params::GGJParameters, Q::Number; kmax::Int=8) = diff --git a/src/InnerLayer/InnerLayer.jl b/src/InnerLayer/InnerLayer.jl index a2ec7adbc..f8c3a30c3 100644 --- a/src/InnerLayer/InnerLayer.jl +++ b/src/InnerLayer/InnerLayer.jl @@ -15,11 +15,8 @@ include("InnerLayerInterface.jl") include("GGJ/GGJ.jl") include("SLAYER/SLAYER.jl") -import .GGJ: GGJModel, GGJParameters, build_asymptotics, evaluate_asymptotics -import .GGJ: InnerAsymptoticsCache, mercier_di, mercier_dr, inner_Q, rescale_delta -import .GGJ: glasser_wang_2020_eq55 -import .GGJ: solve_ray, RaySolveResult, pick_smax, physical_ua_dua -import .GGJ: delta_convergence, solution_profile, asymptotic_profile, q4_surface_benchmark +import .GGJ: GGJModel, GGJParameters, mercier_di, mercier_dr, inner_Q, rescale_delta +import .GGJ: solve_ray, pick_smax, delta_convergence, solution_profile, asymptotic_profile import .SLAYER: SLAYERModel, SLAYERParameters, slayer_parameters, r_based_shear import .SLAYER: riccati_del_s, slayer_layer_thickness, LayerWidths @@ -35,11 +32,8 @@ model_name(::SLAYERModel{S}) where {S} = "slayer_$S" export InnerLayerModel, InnerLayerParameters, InnerLayerResponse, solve_inner, solve_inner_profile export GGJ, GGJModel, GGJParameters -export build_asymptotics, evaluate_asymptotics, InnerAsymptoticsCache export mercier_di, mercier_dr, inner_Q, rescale_delta -export glasser_wang_2020_eq55 -export solve_ray, RaySolveResult, pick_smax, physical_ua_dua -export delta_convergence, solution_profile, asymptotic_profile, q4_surface_benchmark +export solve_ray, pick_smax, delta_convergence, solution_profile, asymptotic_profile export SLAYER, SLAYERModel, SLAYERParameters, slayer_parameters, r_based_shear export riccati_del_s, slayer_layer_thickness, LayerWidths diff --git a/test/runtests_dispersion_coupled.jl b/test/runtests_dispersion_coupled.jl index 1b950016e..19ab7c99d 100644 --- a/test/runtests_dispersion_coupled.jl +++ b/test/runtests_dispersion_coupled.jl @@ -1,6 +1,7 @@ @testset "Dispersion coupled determinant" begin using GeneralizedPerturbedEquilibrium.InnerLayer using GeneralizedPerturbedEquilibrium.InnerLayer: InnerLayerModel, solve_inner + using GeneralizedPerturbedEquilibrium.InnerLayer.GGJ: glasser_wang_2020_eq55 using GeneralizedPerturbedEquilibrium.Dispersion using LinearAlgebra using StaticArrays diff --git a/test/runtests_dispersion_residual.jl b/test/runtests_dispersion_residual.jl index 30ebf24ff..69d9cec08 100644 --- a/test/runtests_dispersion_residual.jl +++ b/test/runtests_dispersion_residual.jl @@ -1,6 +1,7 @@ @testset "Dispersion residual (SurfaceCoupling)" begin using GeneralizedPerturbedEquilibrium.InnerLayer using GeneralizedPerturbedEquilibrium.InnerLayer: InnerLayerModel, solve_inner + using GeneralizedPerturbedEquilibrium.InnerLayer.GGJ: glasser_wang_2020_eq55 using GeneralizedPerturbedEquilibrium.Dispersion using StaticArrays diff --git a/test/runtests_innerlayer.jl b/test/runtests_innerlayer.jl index b23624ebc..c972ad5a2 100644 --- a/test/runtests_innerlayer.jl +++ b/test/runtests_innerlayer.jl @@ -19,7 +19,7 @@ const IL = GeneralizedPerturbedEquilibrium.InnerLayer const GGJ = IL.GGJ @testset "InnerLayer GGJ (Glasser & Wang 2020, Eq. 55)" begin - p = IL.glasser_wang_2020_eq55() + p = IL.GGJ.glasser_wang_2020_eq55() @testset "Mercier index and matching powers (Eq. 49)" begin # D_I = E + F + H − 1/4 from the verbatim Eq. 55 coefficients. @@ -55,7 +55,7 @@ end @testset "InnerLayer GGJ :ray backend (rotated contour, Hermite BVP)" begin # These tests pin the implementation; the method is validated against an independent # strict reference over the Q plane outside the test suite. - p = IL.glasser_wang_2020_eq55() + p = IL.GGJ.glasser_wang_2020_eq55() @testset "agrees with :galerkin at the paper point Q = 0.1234" begin γ = 0.1234 * GGJ.q0(p) @@ -70,7 +70,7 @@ end end @testset "q4 physical benchmark at Q = 500i (regime beyond :galerkin)" begin - q4 = IL.q4_surface_benchmark() + q4 = IL.GGJ.q4_surface_benchmark() γ = 500.0im * GGJ.q0(q4) Δ = IL.solve_inner(IL.GGJModel(), q4, γ) # Pins from the pre-port validation suite (post extended-precision @@ -89,7 +89,7 @@ end end @testset "InnerLayer GGJ :ray internal machinery" begin - p = IL.q4_surface_benchmark() + p = IL.GGJ.q4_surface_benchmark() @testset "Hermite BVP resolution floor at small |Q|" begin # At |Q| ≪ 1 the local WKB rates are small; refining the grid (cfl/8, 2× min_cells) must not move Δ. @@ -141,7 +141,7 @@ end end @testset "solve_inner_profile interface (matching-driver contract)" begin - p = IL.glasser_wang_2020_eq55() + p = IL.GGJ.glasser_wang_2020_eq55() γ = 0.1234 * GGJ.q0(p) for model in (IL.GGJModel(; solver=:ray, real_profiles=true), IL.GGJModel(; solver=:galerkin)) prof = IL.solve_inner_profile(model, p, γ) diff --git a/test/runtests_matching_models.jl b/test/runtests_matching_models.jl index 920e03d4c..d7410d618 100644 --- a/test/runtests_matching_models.jl +++ b/test/runtests_matching_models.jl @@ -11,7 +11,7 @@ @test !FFS.closure_capable(IL.GGJModel(; solver=:shooting)) # no layer profiles @test IL.GGJModel(; solver=:galerkin, nx=640).options == (nx=640,) # Carried options reach the backend exactly as call-site keywords do. - p = IL.glasser_wang_2020_eq55() + p = IL.GGJ.glasser_wang_2020_eq55() γ = 1e-3im @test IL.solve_inner(IL.GGJModel(; solver=:galerkin, nx=256), p, γ) == IL.solve_inner(IL.GGJModel(; solver=:galerkin), p, γ; nx=256) @test IL.solve_inner(IL.GGJModel(; solver=:galerkin, nx=256), p, γ; nx=512) == IL.solve_inner(IL.GGJModel(; solver=:galerkin), p, γ) From cf33eb8cf4f42025799330112d31a9c508cae31d Mon Sep 17 00:00:00 2001 From: logan-nc Date: Tue, 20 Oct 2026 08:47:56 -0400 Subject: [PATCH 09/12] ForceFreeStates - MINOR - Drop stray semicolons left by the formatter in the match profiles Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF --- src/ForceFreeStates/Matching/MatchProblem.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ForceFreeStates/Matching/MatchProblem.jl b/src/ForceFreeStates/Matching/MatchProblem.jl index 3d7cf9188..5e9727e2d 100644 --- a/src/ForceFreeStates/Matching/MatchProblem.jl +++ b/src/ForceFreeStates/Matching/MatchProblem.jl @@ -187,8 +187,8 @@ function _compute_match(prob::MatchProblem, model::InnerLayer.GGJModel) if gal_sol === nothing xi = Array{ComplexF64,3}(undef, 0, 0, 0) xi_deriv = Array{ComplexF64,3}(undef, 0, 0, 0) - empty!(inner_psi); - empty!(inner_xi); + empty!(inner_psi) + empty!(inner_xi) empty!(inner_b) else sols = gal_sol.xi # (mpert, ngrid, nsol) @@ -213,8 +213,8 @@ function _compute_match(prob::MatchProblem, model::InnerLayer.GGJModel) if isempty(sols_cut) @warn "MatchProblem: the solve retained no cut solution (set cut_solution=true on Galerkin), " * "so the composite inner-region profiles are skipped; bpen and the matched outer ξ are unaffected" maxlog=1 - empty!(inner_psi); - empty!(inner_xi); + empty!(inner_psi) + empty!(inner_xi) empty!(inner_b) else cut_range = gal_sol.cut_range From 456ff246c7ddcc9ccbb043b073e53d6191844d77 Mon Sep 17 00:00:00 2001 From: Matthew Pharr Date: Wed, 21 Oct 2026 10:15:16 +0200 Subject: [PATCH 10/12] InnerLayer.GGJ - BUGFIX! - Keep the layer-center values from the rotated solve when real profiles are requested --- .../inner_layer/make_solution_profiles.jl | 4 ++-- docs/src/inner_layer.md | 9 ++++---- src/InnerLayer/GGJ/Ray.jl | 13 +++++++---- test/runtests_innerlayer.jl | 9 ++++---- test/runtests_solve_api.jl | 23 +++++++++++++++++++ 5 files changed, 43 insertions(+), 15 deletions(-) diff --git a/docs/src/figures/inner_layer/make_solution_profiles.jl b/docs/src/figures/inner_layer/make_solution_profiles.jl index cf3043589..6f89b9c66 100644 --- a/docs/src/figures/inner_layer/make_solution_profiles.jl +++ b/docs/src/figures/inner_layer/make_solution_profiles.jl @@ -21,7 +21,7 @@ Q = 2.0im # imaginary axis, beyond the |Q|≪1 shooting regime, # small enough that the BVP domain reaches # the series radius directly (no march) — so the # numeric and asymptotic segments join seamlessly. -isol = 1 # "odd" parity solution (Ψ'(0)=Ξ(0)=Υ(0)=0) +isol = 2 # odd-parity (tearing, Δ₋) solution: Ψ'(0)=Ξ(0)=Υ(0)=0 res = IL.solve_ray(p, Q) s_m = res.breaks[end] @@ -39,7 +39,7 @@ fields = ((:Ψ, prof.Ψ, asy.Ψ, 1), (:Ξ, prof.Ξ, asy.Ξ, 2), (:Υ, prof.Υ, a plt = plot(; size=(760, 560), legend=:bottomleft, xscale=:log10, yscale=:log10, ylims=(1e-3, 1e2), - xlabel="ray parameter s (x = e^{iθ}s)", ylabel="|field| (odd parity)", + xlabel="ray parameter s (x = e^{iθ}s)", ylabel="|field| (odd parity, tearing)", title=@sprintf("Inner-layer fields on the rotated ray, Q = %gi (q=4)", imag(Q)), left_margin=8Plots.mm, bottom_margin=5Plots.mm) diff --git a/docs/src/inner_layer.md b/docs/src/inner_layer.md index 2912528ff..ff3033c12 100644 --- a/docs/src/inner_layer.md +++ b/docs/src/inner_layer.md @@ -124,10 +124,11 @@ default ``\theta = \arg(Q)/4`` keeps it off the contour. For matching, `solve_inner_profile` returns ``\Delta`` and the layer-center fields ``\Psi(0), \Xi(0)`` from the rotated solve; ``x = 0`` lies on every contour, so these are the -real-axis values. Fields across the layer on the real ``\psi`` axis are opt-in -(`GGJModel(; real_profiles=true)`): they come from an extra ``\theta = 0`` solve, whose ``\Delta`` -is checked against the rotated one (`certΔ`, which warns on disagreement, as can happen at large -``|Q|`` near the imaginary axis). +real-axis values. Fields across the layer on the real ``\psi`` axis are an opt-in diagnostic +(`GGJModel(; real_profiles=true)`, not exposed in the deck): they come from an extra ``\theta = 0`` +solve, while the ``x = 0`` values, and so the penetrated field, stay those of the rotated solve. +The ``\theta = 0`` solve's ``\Delta_\pm`` are checked against the rotated ones (`certΔ`, which +warns on disagreement, as can happen at large ``|Q|`` near the imaginary axis). ![Inner-layer fields Ψ, Ξ, Υ on the rotated ray for the q=4 surface at Q = 2i. The BVP solution (solid) joins the asymptotic representation (dashed) seamlessly at the match point S = s_m.](figures/inner_layer/solution_profiles.png) diff --git a/src/InnerLayer/GGJ/Ray.jl b/src/InnerLayer/GGJ/Ray.jl index ee95cac2f..f7e1804d0 100644 --- a/src/InnerLayer/GGJ/Ray.jl +++ b/src/InnerLayer/GGJ/Ray.jl @@ -430,22 +430,25 @@ end Rotated-ray implementation of the [`solve_inner_profile`](@ref) interface. `Δ` and the layer-center fields come from the solve at θ = arg(Q)/4; x = 0 lies on every contour, so Ψ(0), Ξ(0) are the real-axis values, and by default only they are returned (`x = [0.0]`, -`certΔ = NaN`). With `real_profiles = true` the fields across the layer come from an extra -θ = 0 solve (`npc` points per cell), and the relative difference of its Δ₊ is `certΔ`, -warned above `certify_rtol`. Other keywords forward to [`solve_ray`](@ref), except θ. +`certΔ = NaN`). With `real_profiles = true` the fields across the layer (x > 0) come from an +extra θ = 0 solve (`npc` points per cell), a diagnostic; the x = 0 row stays the rotated +solve's, and `certΔ` is the largest relative difference of the two solves' Δ₊, Δ₋, warned +above `certify_rtol`. Other keywords forward to [`solve_ray`](@ref), except θ. """ function solve_inner_profile(::_BareGGJ{:ray}, params::GGJParameters, γ::Number; real_profiles::Bool=false, npc::Int=8, certify_rtol::Float64=1e-3, kwargs...) Q = inner_Q(params, γ) rr = solve_ray(params, Q; kwargs...) # Δ and layer-center fields (optimal θ) + c = solution_profile(rr; npc=1) # first point is s = 0 if !real_profiles - c = solution_profile(rr; npc=1) # first point is s = 0 return (; Δ=rr.Δ, x=[0.0], Ψ=c.Ψ[1:1, :], Ξ=c.Ξ[1:1, :], _profile_conversions(params)..., certΔ=NaN) end r0 = solve_ray(params, Q; θ=0.0, kwargs...) # real-axis profile solve - certΔ = abs(r0.Δ[1] - rr.Δ[1]) / max(abs(rr.Δ[1]), 1e-300) + certΔ = maximum(abs.(r0.Δ .- rr.Δ) ./ max.(abs.(rr.Δ), 1e-300)) certΔ > certify_rtol && @warn "GGJ ray: θ=0 profile solve disagrees with certified Δ" ising = params.ising Q certΔ prof = solution_profile(r0; npc=npc) + prof.Ψ[1, :] .= c.Ψ[1, :] # x = 0 from the rotated solve, as without profiles + prof.Ξ[1, :] .= c.Ξ[1, :] return (; Δ=rr.Δ, x=prof.s, Ψ=prof.Ψ, Ξ=prof.Ξ, _profile_conversions(params)..., certΔ=certΔ) end diff --git a/test/runtests_innerlayer.jl b/test/runtests_innerlayer.jl index c972ad5a2..6cda60780 100644 --- a/test/runtests_innerlayer.jl +++ b/test/runtests_innerlayer.jl @@ -165,14 +165,15 @@ end ray = IL.solve_inner_profile(IL.GGJModel(; solver=:ray, real_profiles=true), p, γ) @test ray.certΔ < 1e-12 - # Default :ray returns only the layer-center fields of the rotated solve; x = 0 lies on every - # contour, so they match the θ = 0 real-axis profile at its first point. + # Default :ray returns only the layer-center fields of the rotated solve. With real profiles the + # x = 0 row is still the rotated solve's, so the penetrated field does not depend on the option, + # and the θ = 0 profile next to it is continuous with it. γi = 5.0im * GGJ.q0(p) c = IL.solve_inner_profile(IL.GGJModel(; solver=:ray), p, γi) full = IL.solve_inner_profile(IL.GGJModel(; solver=:ray, real_profiles=true), p, γi) @test c.x == [0.0] && size(c.Ψ) == (1, 2) && isnan(c.certΔ) @test c.Δ == full.Δ - @test c.Ψ[1, 2] ≈ full.Ψ[1, 2] rtol = 1e-6 - @test c.Ξ[1, 1] ≈ full.Ξ[1, 1] rtol = 1e-6 + @test full.x[1] == 0 && full.Ψ[1, :] == c.Ψ[1, :] && full.Ξ[1, :] == c.Ξ[1, :] + @test full.Ψ[2, 2] ≈ c.Ψ[1, 2] rtol = 1e-2 # odd Ψ is even, so smooth through x = 0 @test full.certΔ < 1e-5 end diff --git a/test/runtests_solve_api.jl b/test/runtests_solve_api.jl index 18d4e6082..3de6f581f 100644 --- a/test/runtests_solve_api.jl +++ b/test/runtests_solve_api.jl @@ -244,6 +244,29 @@ using TOML end end + @testset "matched inner profiles: opt-in, and parity columns agree across inner models" begin + mktempdir() do dir + gal = solve(equil, Galerkin(; nx=32, rpec_flag=true, cut_solution=true); nn=1, dir_path=dir, ffs_kwargs...) + prob = MatchProblem(gal; eta=1e-7, rho=1e-7, rotation=1.0) + center = solve(prob, GGJModel()).match + ray = solve(prob, GGJModel(; real_profiles=true)).match + galm = solve(prob, GGJModel(; solver=:galerkin)).match + # Δ and the penetrated field come from the rotated solve whether or not profiles are requested. + @test ray.deltar == center.deltar && ray.bpen == center.bpen + @test isempty(center.inner_psi) && isempty(center.inner_xi) && isempty(center.inner_b) + @test !isempty(ray.inner_xi) && !isempty(galm.inner_xi) + # At ψ_s the composite ξ is the even (Δ₊) column and b the odd (Δ₋) one, so a parity swap in the + # profile assembly makes the two backends disagree here. + for (i, sing) in enumerate(gal.surfaces) + ir = findfirst(==(sing.psifac), ray.inner_psi[i]) + ig = findfirst(==(sing.psifac), galm.inner_psi[i]) + @test ir !== nothing && ig !== nothing + @test isapprox(ray.inner_xi[i][ir, :], galm.inner_xi[i][ig, :]; rtol=1e-4) + @test isapprox(ray.inner_b[i][ir, :], galm.inner_b[i][ig, :]; rtol=1e-4) + end + end + end + @testset "a resistive match keeps its coefficients and drops the ideal δW" begin mktempdir() do dir ric = solve(equil, Riccati(); nn=1, dir_path=dir, ffs_kwargs...) From 5d11aad3e7e59cfd0937b89e44dd327c86080717 Mon Sep 17 00:00:00 2001 From: Matthew Pharr Date: Wed, 21 Oct 2026 10:23:52 +0200 Subject: [PATCH 11/12] Repo - BUGFIX - Record clean figure provenance and ignore generated figures in the dirty check --- docs/figure_tools.jl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/figure_tools.jl b/docs/figure_tools.jl index ca8001be5..13b91d08f 100644 --- a/docs/figure_tools.jl +++ b/docs/figure_tools.jl @@ -29,13 +29,16 @@ Short git commit and ISO date stamped onto every figure. `commit` is the `git rev-parse --short HEAD` hash (reusing the idiom from `benchmarks/benchmark_git_branches.jl`), with a `-dirty` suffix when the working tree has uncommitted changes so a figure never claims a cleaner -provenance than it has. Falls back to `"unknown"` outside a git checkout. +provenance than it has. Generated figures and the manifest do not count as changes, so +several figures can be regenerated in turn on one clean commit. Falls back to `"unknown"` +outside a git checkout. """ function figure_provenance() date = string(Dates.today()) try - h = strip(read(`git -C $(_REPO_ROOT) rev-parse --short HEAD`, String)) - dirty = !isempty(strip(read(`git -C $(_REPO_ROOT) status --porcelain`, String))) + h = String(strip(read(`git -C $(_REPO_ROOT) rev-parse --short HEAD`, String))) + outputs = [":(exclude,glob)docs/src/figures/**/*.png", ":(exclude)docs/src/figures/manifest.toml"] + dirty = !isempty(strip(read(`git -C $(_REPO_ROOT) status --porcelain -- . $outputs`, String))) return (; commit=(dirty ? "$h-dirty" : h), date=date, dirty=dirty) catch return (; commit="unknown", date=date, dirty=false) From 2a270ca033ff324e18f135bf6e2f9e27ee56baf5 Mon Sep 17 00:00:00 2001 From: Matthew Pharr Date: Wed, 21 Oct 2026 10:25:28 +0200 Subject: [PATCH 12/12] InnerLayer - DOCS - Regenerate the inner-layer figures from a clean commit --- .../inner_layer/convergence_Sinvariance.png | Bin 51966 -> 51719 bytes .../figures/inner_layer/solution_profiles.png | Bin 53329 -> 54623 bytes docs/src/figures/manifest.toml | 8 ++++---- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/src/figures/inner_layer/convergence_Sinvariance.png b/docs/src/figures/inner_layer/convergence_Sinvariance.png index 094e9737066b08e8d6c505f4a150e6cad93aee65..cedbc59056235c9b161230ae02689f330ad6e06d 100644 GIT binary patch delta 32133 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∈<! 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 delta 32382 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 diff --git a/docs/src/figures/manifest.toml b/docs/src/figures/manifest.toml index a8ee3c49d..731585bc5 100644 --- a/docs/src/figures/manifest.toml +++ b/docs/src/figures/manifest.toml @@ -25,8 +25,8 @@ depends = ["src/InnerLayer/GGJ/Ray.jl", "src/InnerLayer/GGJ/Galerkin.jl", "src/I script = "make_backend_regime_map.jl" [inner_layer.convergence_Sinvariance] -commit = "5b51d871f-dirty" -date = "2026-10-19" +commit = "5d11aad3e" +date = "2026-10-21" depends = ["src/InnerLayer/GGJ/Ray.jl"] script = "make_convergence_Sinvariance.jl" @@ -37,7 +37,7 @@ depends = ["src/InnerLayer/GGJ/Ray.jl"] script = "make_rotated_ray_contour.jl" [inner_layer.solution_profiles] -commit = "20887ed8c-dirty" -date = "2026-10-16" +commit = "5d11aad3e" +date = "2026-10-21" depends = ["src/InnerLayer/GGJ/Ray.jl", "src/InnerLayer/GGJ/InnerAsymptotics.jl"] script = "make_solution_profiles.jl"