From 11587786e06641851a2c28a6b753105b02575541 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Sat, 15 Feb 2025 05:58:30 +0100 Subject: [PATCH] removed old command line scripts (#3300) Co-authored-by: Paul Romano --- docs/source/_images/plotmeshtally.png | Bin 72643 -> 0 bytes docs/source/io_formats/plots.rst | 14 +- docs/source/usersguide/plots.rst | 10 +- docs/source/usersguide/processing.rst | 11 +- docs/source/usersguide/scripts.rst | 139 -------- docs/source/usersguide/settings.rst | 7 +- pyproject.toml | 11 +- scripts/openmc-ace-to-hdf5 | 156 --------- scripts/openmc-plot-mesh-tally | 344 -------------------- scripts/openmc-track-combine | 24 -- scripts/openmc-track-to-vtk | 41 --- scripts/openmc-update-inputs | 307 ----------------- scripts/openmc-update-mgxs | 212 ------------ scripts/openmc-voxel-to-vtk | 22 -- tests/regression_tests/track_output/test.py | 5 +- tests/testing_harness.py | 4 +- 16 files changed, 23 insertions(+), 1284 deletions(-) delete mode 100644 docs/source/_images/plotmeshtally.png delete mode 100755 scripts/openmc-ace-to-hdf5 delete mode 100755 scripts/openmc-plot-mesh-tally delete mode 100755 scripts/openmc-track-combine delete mode 100755 scripts/openmc-track-to-vtk delete mode 100755 scripts/openmc-update-inputs delete mode 100755 scripts/openmc-update-mgxs delete mode 100755 scripts/openmc-voxel-to-vtk diff --git a/docs/source/_images/plotmeshtally.png b/docs/source/_images/plotmeshtally.png deleted file mode 100644 index d874b4906ab84bcf11617f116a4ecd7360aa2ce2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72643 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�+IC#>D)3I^1hid;L>$ap*P%UA~gYNtAFR)_j z>gsy3AP1+Ea3yd8wOH_7ugyQW0F)A-k7xpJmyVV;4~PLWmHzN#Tz=XO+T7W)PTWMU z)FFaWL<^4f$Up%Q`@aAC|6O7(7WIpi7L0T)Xsd){8A=uQLh#8rgxQrV1unU`l(K-OTIL&)Ffj1AX2X-)D-M0)_ zMCQ~#W9jI-ZUm}8nrgKE6@F{HKMXCI?>dBTZGgr;+|OJ~D`{@o5sasv&w}AQWfhe( zAZ-YckG;`?IPOGGw@W}2^6~fAwI37%#j~0HW`ncaB|tB#2C)T!;6EJC0o7{83&49x z&!uYXcAco*wW8UkM>^axolz=-91(iR1{;wdkKoRqes! zliwtd40uZ(xvGc~NGUK7+)an7u7so{ zUzAJ0MlE!HznAYrjFfWap1j-baC5b{-H?cuOdHR#7CFV*YLea1UHRn;&7B4xZZYvU z44yl&5F2?TXG%edNQ1HjRV6Dm?b1c^>rdMvG)bY#;C@Nt@BgqOz=Yfu)H9E2`3t#u ziFD2(?$5D)bUyzqGYQc!bFKc0NrS6gNg5-g zUQoT>WGZ7Jt4$BKvVZl+o(6&IBFeoauPG6wRplj|+FhoV66-mrg-MbR2Np#{0m zYW;o#7G!RyXd^Wo`|O82F1#>u z1LV-=wDllje_Z$Gn^n#Gce13xqgUQ;*M;6*GrDd80Y@#!81S|y?EV7=lk~F%ex2F7 zSL0Ho0Neu zf3~{Ju$xBPKdhSjqe>$7(06L9+3C+HP2fN|1rhsqnUrXfUHb&UmgcTtjO*q`Sv+M7 zMGVVw?LY@02MtV=QfKrFUhf3a7sKZ7I4i7?#N+`v%_`M?GyFKNro@H4Lbop4SVvhA zF5xJxjGb)~l+D^+QFmu7rN4!`KllTShNRYID7MF`+qBP^VxFdx`i|4-EF-ccB!xt4 zx?#pFrtqFFGT16#Xy5;GvXS}SKX2K@?h!Cdv{alIqx8KhyS+~ee>Lnpd(QLxF>>F_ zJHC3Ygwl&)OwG5(8fb6gTTQFqMP|KtS5z>jxJ*XgSKDL2!=S)6J#IChYdU3zC7xYH z`vPT6qv&+I8YfP9+%yR*LLwFoJ9g$`ErUe2Vch)bL}hu9xEROjBu*J6l($pqoEf?D z$N*aHW!+9gspHA$glih(Qb=7gMo7UEb>9J@4tU7``9_e(Z5?u9G@kXDW#dW*YUm{q z84>Dh*1K5jz$SqEIA%nzA=@`8F!Sef+{>le^nfNsUE#9lTGu*Com%3q1ADlluq6Yw z^c3vzkofkRHvHuz?s4w*!w4Dmr8ji5aWZ#UT;CKCukxuR@~d34Aujg8X8seY=F-27 z#PYHcnmfU=p&NWgYLeZVy9sZO4&%3a8$eWcv@sTNU@iIfZH!8Cnp!5MS!&t9L#J5} z>O&`Af5GX>eYMK&$#vL3z`&2+FWqvrV?W9k(G*wlQcsnp|EAieR4-Q>xquKl-PW-4 zoR0mPr7*vz+08Kcs@_D==I5BHH%kAkm?)Ocjj^tdyl~cW2kt(~!b->?j81`l)p`<% zS)vVugTyw|n2VS7wFTaETriRDYo5JGBGiTUk#zss2`7&@vlLGWO1G8AtQ9VUUwh|kx_560FcIE7% z>ALHm{q?8jQHuBrEneF0n{pE5tlw%R)*?ry3M{e3w3|JX`~5*SspoHBPrrSrpQ4p% zXMX`@c5utD=FyhN?o%rm1F+DiGin4N47_(Wop}eDTP7z|Z~lF2)5g|J$a!m<*c+P~ zQ+ZL^!TL_kr?a?Y-l9*alU6?!W)&l_e7~UA)M;6Z}UU(_B;LFAqj<~ezR<`D>qolm)11{X}CF;z({Ht^AL99lH@!+6oNMl z7_E>c>xn`X+qVoj-MNWO*A9IZQSSoh^rH&Bq}?_N)*nE(PhABpG~fXER2&-$4n3;j zuEr7ccZ!I}>Q}K2PolGlOxm0N@ZjKMXMUF1y4i!P?Nq@twL4Z?g{sX<8jFBt`q>j` z6JpS)W%-mrlsRi+4^BA+e>4fd`~KH^W$n+izlugekT>r|h|a7PG6`L-ru3w++z4yH z=x&NWR;o8z%7#kBQqs;C-W=z?9#*yBX|3!N&F#gUK*C>ss9aJ1f{T-toVSf!5_380 zom3=ycs@^&LZE-W!W*Z~yB3Ii=IEM>S>viYwcGw@mTE2fZ+%^6V@^$hZ)2%~)vMxH zmnf!#P%WZ9c2Y`~Nw9X7F-T@o>&#jlkj6yio${QA)MVs`u*BrG#b@Wa&UJQlkL_Q& za3#}O+iqFs7IWy0$f-vLP~NciaE>Ihf0M!jh(-pPNSjQYih#}C9e#vUG|!QD^f*&R za*1Q(nUw0ZZ7PqmWI*0mHll;yF*6)G*p5fQJ|DJ4G6yi$tG z>j}hC-B~0=+iAR8Y9i~4^?TDaPFKMC%^-YwTUohrCaG1=(+>94Klav|+N@H}vv#{n z=;nGoj>NcgAvopw+KZ&I7G+!)M``$W=*vXFfk(_JhE6?0XA+y(a6`hHymEC$u2!&Z zJ8$9U;v_v<9FO+iz_Q4`DiKSx;+De5V>ha*+nD4>`sM(t00oWX+pB{Lq?;<{TgBc* z6i`(GoI+dg5&B@~mm)CQp9(uUT@2)!gZ=I?%8^Bm(!|ZNmC5f?l2%j_kIc$X$TvyI z4<&KEU1-`2!B`G43$ba(U)Hjc6Ah?5Q7gr8uU0{2ev#O+lzga{(_UF0&fiqBmUe6L zg~RgoNoqk=9MBylj0KDS$+2MfS2e^Xe21q8e+hPSQFVJh6Ejn-3ugTRzma=gB^U~_ z68@Bc`1oz$WqQ}=Z0aK**e30fpR_;AdAjH2IdBBqr(?!`j{7?gKgkA~IigaZNmsVl zctVa$qbz?)PRW(!u-s-*W)QI=1hap|{JT(1*M;Ph^)K}FKN!RCB>-XcHOreCK_Wk<-iOo}{jDzitYY|N5Vlaacy zxkuTp1I7%22%W42Ust(fi&2zh#9LH7sfR9dhRX!8B}yk`yC{uj=36Q|&H2ddFZG!|Hsj* zW>%%B$q}lNU))AXCJ7+Uajz$|;{i7b(}XU(bt%lCPt`u{m1uOhcZY3!khM*$$>Y~` zv(6jel2lb=OU9?usXKBS=d=ax>OtvS!eNC6o|!#@#j~dFGh+AssyuyGKR%0e5|W$J z_2|U<(@jEre03Lgv(E8ger%d98JzPvd!=@4F5m(1yI8x#;}T7`Cy9rb{g;mPtfZ7z z<5?X~y{V|dqWzG=+I_V{d*Qsq@NE!T93<)@0=%ixOp{IaO*`goR;4)3;=FBkXp zlWe3TXD!3uEIV|*DAFmYYr)2~B*ekZQFY>Mc`1`*XUX+#zTUJgIn`snsxkr86)9fs zr>(z|G)mry-d%XQW!~cq&MT~|GP#Su`p)cmb~A-ISu)F;?t9+Mke@E{okl-{JOq+j zLe^u*War|hdmY4fRj8|Wb<*=~6fwV5=ZR!&q*He#PI+JeIPmcFae}{(FB}Kt^3#aM zt^%!#t^B9u5~ytcr;zxg;h9v=yI)DyvU6U$9OFrj*nL!D@_72xeZYhCj=o)4T0bd| zfC7_ECcyaycd0F)TcN z@jfR5hEw;!{7yLKPsCXN;ARf-TxV!mI1zf=JVjB}iRFq$0E9xi&i2`oCu~lmBeZBg zR{Hu^S;01%pv#60I{~t9dG;G#1Mv*6MSohI?xx73$2eX?`Ku>p`zI??HUd$-l(aff z=MAMkq@21R@nF=KrO%m={DTc6xq`quHnVRZFE@kTnkyWgrpHX%*@9L4)p{)Iy*w&2 zl*XKOF7~Hz=I$cxir+@I;l)vf+W49zw0JceDCZT76_|vuiT4!c>R)|74+)RBf6aR{ zkzB2LRry>$P=b|eHzG`}hZO@L7JIYx)d0<*adH`E{Q>|Kr}gLGM*vzrW5} zvWPtB!M5R#317w#3D1hpVHC zOkaD_wP+V|7bnDl)+~&N5TqeXAb-VQo;kfe~HQb7^3f%pk#5j9ZJh8%xiNoBUb!SYR%x_qGZnGu zY(}KqGTv2x)h&jKma0tD^#JZCkm{}Lekc|t!K4zbTpY{5jQotP!wc37PFIifQ zZh?p~P+Gxq(e!?(&FYr*e6G0}H!+q;5)(sAT%1)!pOvLp33EJvjoh$$L{yYo!olIN zj*|M;bGvG+c(vl4OmI=p@~XjN5^f?xvu>5+Setx=BO%6S`T;KAIsKJob-SRDTH53J z$ZS78;p8zD(csXr$ZtuS+V!g&HtihbdLd}i+r|E~ZJn!!Gt~y#iQ~LQlCF;RSw_{; z{~s;lii=C0ul!VjKKk9u-IHKh@l&4whnlt>jMq2P`_PZmM+L6#@VS@ z;+|CyQ<4?K7}5|JV0T1EFwP!&lJ7^EN5?_(MY4@i&%-iL*@Zjl_*u%W9E{kD9`-4~ zR1G*e>LZ8n{Jg*<>P`m4v%?jO3A&fp*0;0!cP~ zwHYQ(3_5mxW|bt`#L;t9w{psPv!X%Su1d<}o3Cz>N;1G2N-45u8&54%WUc%-h?i3w zKm||{Fdrv-Y}WcQirsFHFRG-e>LpjsVEn~Ow5pI6dE!bzaWl(|=3M?I&w5ZskPEfV zUQjU8hW7SZE`&Mmw;s!O-Wxv=f4d+(jfno?=%rH~ZGP8UkD?U!47=ZCXwZ2Z>S0hk zz4AwoU#Q=!d(}5e5Q*K_kmSOByz%QCKk}oALUZ)F>LF2h;&;h!9CeZr{w(eB?I-c^N>pLv{7yF` zcy9_QD7?&UmPBL6$6z&;Kgi|GDt`sU3BD*OcBpL>jaF5Oxt-9>6y6nTaxS^-VLIE{ z`pV8Yq^Ut^+=r~nG!KQFp@RDbl12Re{U$S92TdyW7q?-24pwl1{TinZaZLvXL z{i@lQGEi7J8IAw=S_k*p66I!`L{$;D6h(gaVOm9i7w zR{iGZVdu}2bbp5%41M0vcmv3ixpr=xUo@L18# z^-LbIKR6t9WaR^AC!;Ew^uDr6=DQX_+vwKkmS~PuoxZrJbD#nTJWsGu!4FD_gsXx) ztA>k5Zh@=nM@O-1D3z$azkhQ(?%<8?x};wARZ~hPPEXSC ztVPT_WL*h*AU{YiXbY6u!iiWiRwZ+ro+fUbO9_k`=2SI?;x)+c^ip*iS}xxOaIfRW zvw;-jz+n-q<}v;pct**>V1rU8>SbhdC<~M=FFf`SmDUp%#TZ1IStRQd*>UuJNPV}$ z6^E8;+xhc5ADU%v*XEKk2LRz%K78<2P<(T?$MVC?K8=;)ORb8TfDM$2hYFi{j+=Uc zO=yOOXTh$j_wwf22r@BW;q^C$UM=Dk8X79lN|jP)xI%vikR5sDd1y_3e&Fnq@~OK- zHoCud&xMMz^pIIYl&ENAXHp90UA>tm#vWHjewTjfxl1ENd}{LzJnicMRIiF+UQI>W zzH7I4?n!e@OeH5TnwZNNUeI12Oj6g!Co2qgV$DV>@~3=SU9o?@d*It#yVK!o=EXUx ztzyQ=z4sD>&*8D6juV?=9}mWQh+RpCS=R=$L?opIlKdixOub;6DNhvQK!Mt$jZv^* zuiS9q>>l_J4RW<{q(4L{d)NO<4KY2z@yFnk@BQR43bE*GU7MGacNfXunJYy}!C{KjuUm+2m04`^0d zMt!UWbAK{9!|N`(k(3Ws5daHjeP-2`nBRF|`S2MbZ<{$M7nT#(>nC z7jUGjr=AUvM9pUS! z5dNB~s@N@ZtG?RXNm2<+{b$o)D_Ufx@`p;JP~ePTe^lq}D~5#A0FERezz7TtCw@bR zGrKz4@e1U%VHzash!QS~QP$#4|ulQCX6NaV#5=5x4O~L7RWP=ym$*o-(l0n`NvXJ-+tfcdnc5j3$g? zCxZ3qHQDmd!J+@FySEIBG78&8#{w0QQb1BdKq=`4k)fod8>G9t6_peaDQW2jDQS={ z2c(-pYUmnZsA0~+Z=dVh`|R)A=lgrk`@_p0!@RTByWX|#=YHyN- zSde#Ba=4AWirEb!j?2puaE!wm9W4MrGQUq8-0qK$Djfxg9y(OtTT*jvLwRyLUNGld zd!G9{!l)@e>6zYyRFf`k7+N8dOX4y5KXjYVlVpNF4cu+K0nt@%T2#fad@6V7C8AlZ zp|E4y@N8EZe951Sj15g#XxyCR)yZ&7fTx%UZJWaQZgar@tpzZIX4eSnl z*xElkEL7yDqGtcrOqC;shlQ~4&cNE0#c(*y%KvrUjpDo!pZM2D{W=82l=R(97>B_8=8R>VxJe3}CTN)ZJ^vARCDzb2JFl7NbfnqX` z92_$Ns;~UNSX9%VCQv^65Rywkc&rr7I>qCPUWn~~l0Ob#OsBulhR@aIFCA8>R9;LC z)#n}cSwFDslyq!?pXc6ye6PqGS5i7&pVTJ;?3?M>3r<3?uk=oxMMXrU2)P$|t>*Tb zjg;5NnV)TI2&>5d^gkO$YYE?Q z4V;Ize*Pl#xCNRw7{_m|aYQmGl@Z&}-dlqF%S7*xI##;~qfmHJRv@yr`Rcf4`2C;W(1t2fC9$%0z ziPgqzD!O~7i)*-q-%R!}3EO!jpAlH=m9#u!c<}RU`(^{Sf^mh?^XcP`sHRiegIB_R zw9`W=e%|eB8Lb)RPZzkVi<3edJ+9E+*9EtCaVuuzvYAsuL%FkOW^>2LKTKP9Ge@IVJM7YQhBI79i40Y zdhx|qc|{6-o^E{<`CUXHpadbe!PVSlu% zPSsrMOh?>?Zg=K*SIseD{yZ^X2D6l}>WF7+*E9vcNJ*>euHdDh(q)Z}-TKm?9u zGKd0tEui|!Cv|^H7u)AHZJr2>hm#Z-<-Y#5r~(o$AePh6G6Wq!(TZLP$nyGp=B>I2 ztsTq>O-d@U5oI`d@1N{2fP(~gS9IUCO1w3Sh z*x92tZ@Oh~sw0WhR~Pl3X`^=|j8^rsE~0!_Jo$6Zo?$%zyEfw$o_gzUPhC=!vwe%Y zX9(4`vc5Xp`BQFysQIf`?ZCzp{9t}yDq2@3u*_3zTaCY@_T^elxyb5VuU|ar2M1ms z5nWjssI6Vs>9?eFr&Z6c6`q>bx;Ae{d8(!r+%xN2+Kjo9M5u>AqL7_Jcx^5h945bX zEVz=s#x|}Z5c#>e8}DoS%;++S62x#(3D}UkcSW01HiKM53zef=fupRdn(C1ZT8!$t zERl-bv;?#TMJAM9tAp%nXOD*<+pf1Dx4(Ev^Ug?rA_j;)HkN*1q^l!XFipu{W)3BC zeZC6`X=oG|7gtq9Q^5wy%F3jF;r%;XfnRm?*jQZLF3=lYOE*qeO+VMqJ7{R=%%=t4 zfIP7>)8R{jc{DaBi8@lbfG-NTXQl(JArR-xU>11Zc>aSE|1G)AIGDG9djg2hoa*2x z7SIAwllgRA`491bzfS~2zs%D;QLAffz*v~>HkbymG62K*m55kPO|3-J7J0z$P)l`-E-<%m>iX>FisGb=*q&o{$RdXUAo77G;mTJ{Vb#G8zuE` zjA4!QCYPmwSY&}jykcx$0&hb8JeS^|KPrznm#$l|PIXKXhhaTEJ+a_OMsH38C|_Mo zAnn?;@j=BlVTXg_XaW1s?5WouRBKATED*3<5>_=+q`f+>CT=#0ZlbUcIvumyhq3Ut z9?#8+$9si^GT3VSMdJh;IU_YlyR~&a$0|jIXgN6 zEdfW}*athgub?sOxXmNAi)4rJi&4M*Qq45h14fKZw*lJjwfn|_C_M0B+UP{9=@cRC z`_l${mQs9|e<<1(#tm3zjU(=sm`g?X`uXne--2RdkatmicN-%IEP$R6)P`_^>X^<> zsN63y+de5?Hd$e3M%3o~fCLncolfI?)aLE$Nm?u#Tkv+;Hc-1dzq8}Fu^hrEV9S5f zfWVq=DSg?Nw54_>q$BsfjwyQ+dKw(8c$?U`*sZnJ8um-A)@HWlm8^Qq@8%W$ zQI2SS;uzh!!^m2`d^lzd@7aVanjB>Qily5;B_!HFL%&y&l0Y;o2F8+;!@!BT_&lma zUb5}}XxFG_jZ7+Xo!Fc%D^zUR@dBn1^PtoUF^QAVbZmUS75%`)=1d-b*@Hh=yytD< z#Hx{6qJ-;M{ch71!UWJj(O=~(u;CfshWiZGR>3tUQU1%~5n3mKWiBA zM5;eF?(XCOtx9=bET_>e2E?zB1;1AFaw-Uf+)8)nqpKynxV+EHbvO&78AADd!+D+! z-5$#6AV>biHL?kvHHldOd_ckqA=1*2-GRkNDo5t9LSq&@eno@fcgwAHJ zQpA&yUK6>*WvPB=f2v=ob@Y|wUvF}y?PrDH@M*t?NEJLcvz6T|9^INO9uuy^8d|V}N z|DUUG%%$5~BzaXnjHK1=h(KPtlCS!y#YWnT{_Qm5s$uw>qN|5UVHwwOsQfe?AJkkg zvNK4*K|$~|mShAbml7%QRn&Mf#~15!gIC+<#8y3Lw?p*f$k(`hRPQ#yk!0Uh=sa`J zG?@k2$btG8)p9|C^rR`d^piiQ>c~<|4SnTjgJYP5a(jGsY#ME|$p&(dgu_*ThGjuh zRomaDM7P>}Tq%7_w7-mGN6=6*b2utErgrEC<@Fge_)Z%vp+TGIvNH?E-lr&B`A}{H zVT++lUU|>sbgn1*j9*#hBso4OxBi_aBH`wvf7RUr0yLcJ{{f+r@mij$X-_f_tUV1( zmxMCvX(xU(T;8ikZgMuiQn&=zD&f+!Z>e^I1#0Hree(Kld}#GyNk)r)f=&^^bk-1s z$E0Jq!cT%{$7<))i^HxYdY9J)D4E8e90%iLQxdLzW6cSPEIcQSZgD#NQi{=UUXvZN z^%Y_mTwQF|U24EBO}Ah!JAwhe(ek<{sz zIkp%G*^DvQ&X!syJ11gu66#Y9*;chAVRXh%t<}zjoxAWLFOi*7=fHD+Yoe6f2AZUh zH^AP=%FYfn%|N^Z4n4lv^W&}ZhQs^$qZ^Lx6RQ9My%g@GSeX5qj5U`!@Kra#NPVE# zH9)_CV96hE?1j2{e`VW zmM_(u0X{-^I;vd!GP9F1o$ItgPx`5L#n!(y@F?N@I1V%!2HGhdP)P_77jUxrJX%sV zECw=!0PU_%>9bF6^1?y0msyjFb%Z}!IV;kmtt+n6)vFrdA*E5(56O8+FpDA_*i*TY zVmu#_bjgqh27Dg4*C%*D1;FzzF144Jmq6?<`hzd&sA!>Sc#S{JK^#04C3)q&yoT>{ zb%&~7b3jSKSlmOjN~>}Y7{JRA5V02&Of{La5I$vMn%(h0b3-oX0LEoVSBd#lHrBQA!%)o12^4+om#ARRD7lIsteV%OIze&&|fm`!v_r z%8L2gD<$BJ3@9G;G&JTai6Bo-|Ia{6i8$ptAp?2&{lB4BzBY2WBys{oSHbn026CVb z1C`E3#)1ERl4Z^e8{n5w`aL$i+P=zb+eolHkWJBguv?JSr>U-q1Md5a645=}cIyOH z({l=!k^caXn#QrLrly?S#;^Cc<{kJ6od>&+0ogw&u4ADA-uv0dj{fPgV95awyX@?2 zpPYPt*AVaj&#)`LQ9+J1UZXvjbHRg2RJ8Kl5yIPnQjmAw2|OFSPW3RjFRmDD{B)mS zZUeaTd9iWBi1awpsd-cY&KH<0iu1mJ-*Xz5b&5)L<=<`I9x#U! z-X>*u#C@xiVUi10>HN&Ts4#Cn&wBXrg@&dnZ{)JNMTDBta**xw2ny|8Tbty9CzW-O zn+rH7!(BlHs^|UkjoT7b1n4HCa_hx~5Z9sOXoR0394R`)jm9ua+vt(gt0Q(6T#p7h zsk8z%PL*#%)(QHjU`P?(BkzGk?82-0e#uuLP$M$0^^AR{ZX+CHnE2H*mag|v%`-oo zN8+%64J3VAEaocF*T3wXv}AB}2o4`8oKLa5|A@j;3=_Xrf5uG|xh{JfV#U4cR(`5e zA{dX}nWUh~hM$^d;jlE@vdza<_>8{4yq_{bU+1~`jnE(M_RSgaL0Nu_s`saHJErXT zBBitKc5DqFI?Cy_dm0Sq#mhi%`P#r5F5`N#bXhI=DMvheUAaT5|JH#mFk6>CZK?vGjL)b)dzqPKkyz>=Xn8Hw8TgqG6y; z-qPGWH#hg};)45r(39%b%;e$_$BMOD-s#nOM$9u#&y%G`*xfD3>+J+FZ|Yrlj{;LE zk0vgnJtnzNmNWwWO>25$XVkh*6)}ZWVo)#YmTF*YO)c>aCD* zp&C?HH2s!o^^+72O{%!-LgB}aDn|Fw8jL;!;_%#MJ0V2@I_zw0c^)k@kEKNB>oe_A zHRk;adg2-qHR**wWT)04%1#nRivoeECwq7-}_;!@IEot$8k0|<6p%*vVAj{WlrM1HHV@TkD$aAKa1 z-h&(t?fn~D!j`(7^A*Wy*ipbn_+U+zCu2$@XCojmE|Wd5?-5oH-+30@5b^9__~$BHW(bdLy?Bk~P+8CIecK@Gg!m1J zRa#s=sHg&dp5E!@B_#}5peP4a)5#q>7T%F6`%t}P^LN%cU^coZ6&v<>xGI^N9;?2o z*+Ff1@g6NXoyq)#xX^KwIP3y}u;_R{lCIn$@GIL}F=aS}fgzZHP%5M`-XTyF)qB<; zCau`mQVJ?kj}h7VEu5UwX-~uV3#Kmmixl&jL@B&IJz;b9GDRVIb=RcXDd&8oJY75SqB!rjVo<;2_{L2eaOHW zCWztNPH)S@qu^f=-}kCc2n}^tP8E8JS{({33r*%jzaCEMRcY}Y_hfN-kXHDk(x)bE z%)-|fXVCo-)9cOC%CjNGx%Zco6=j*TAI~`1qe!qK2x0iR z5GNLbuJiudruH!XyQEw4GlztB2QE8sexI;GvYH-MpqeEHfzM z#89?jvUX#b^63`Bud+SiXbKrERexV<+Eskk9nVN>QEH@H{CKVN?wO9V^w#e07k1l= zWNS!R2zz&V->R3m7W)TUNS{JV$7vyE)AG1PYo5Rj#ZKIo{HUWCIo8JT0U6(H! zD%}vjPLDIt7d@ZrdJj~*mWUvW{mDmuYE|t&$DG=o_4UYG3Xk{MCMXBybf}y#NBI}^ z6M@NZ>X)mcxw!C+Hq+MIL&q;#F8mq?>U2iOaV*)+?Ig<|cO=`rHRTXhWe65Md28c{ zpWv1MlD_Y+o{wQQ8(e3Ha5rDqGw;p*>-$!fBjNJpe?6_l2K&*|tE3eun)A9UC>!3- z+GXM!kOqR7V66 zndEf$WmEXTzDjd-F+in^Qd!Y)U+g6fG-`Q!Hd0^j4$a{_cSCZ&fOdL6NEPszMCe3R zVt0y@Os}5}eC5TQIz?XUt&Acq@LVEOU)Tl@c#7L8VeFcdCL8Xce9e9>GT)McCjaqO zMOP*Ye;uXU6xW(Gqoy6+ahVpSuBB4E$xs zhpF>00RA!KHmlx-3#*xO*HpIc_umtMxEko|`%94!x+K63yuZ!3oGE)=e14rfVp9Wr zd$XmZUXVw!QTPg1yj&DOE9wLdbxnkBpw6|(15B^3g9mK`uf0!u|Bk!R4_0x zr6@3}#&tM$3V{&M$(5Lb?{R?O?TT?RW^2y1uv4U|Mo7C16T>6h-xF@l*N&->zfC}aT z-X`&{r6Tk7gN<29BHG?siQQtMy-s@BQ}%$W+l08dkDortwdpp9^s*Ssb*#8}F{M8T zYv!fRUS9AUc5&~%7YfG4##XYSM-CBzQP{vEtAR&?0A$ZSb`~U|poyMPnovtlNqw_)~E3$J-RRSn2@2JNO4Z(Js{t>7aefVg!o%dn!x7d~djwjx{}92TW?+ zqaUorlUu?Utl*x{%f7T7PnVFK|)a26F_i?;oCkA%n|}089_K-aQBc z=p9^tB+7*Sg!_MDF7_}pZ#L@)E&qMa38yh{-=0JJu$$(pdi`T$=*P{bdEcn?+Ivt2 z-65)Z&wT|&rfu7~%j|fje?AXR#8&Ph@|h;fzY(qdjz_wu#F)!g2_a?iz(9`tyuSJL z)}!TUWjLyKTH-uvL9psfriv|<;rbW6WU`i&ec-hiU+9eIOH$<%NT2OOaX9yz7Bh-$ z2zU->clvt$F(+Yb$x}Wo>7Guq$6YM$mI+PgK1%Jg84C9%c_<7o;ad5ZiJ=7-5k|k) zEuYA&X4c@4no~2EtclPQ(R|~xb_yl#Fq&&U+RB|pzV83+!FA-d)I6ywB6vp7o@=^A z8jw+eQNQCI%!He9x&FgJIwABloC*gM-%`GR*_A9*6JcZqSBYiH0m?I$05?CW>{z>l zZ>zH{Nr?g93${%Zsj^YwvUQF#*^;kP$%Z{F23lM7TXvvQRMt(q-wxMsJ~Rs=+s?QV zX|KPD*{br-*Pwl`C;FFt3Ep45hhFK3+>Zl4Cj!4JfoB#is~t(%m*ZOJR=Ju{I%;mG zUZ3En`5AXdb;CW%F8^+!>fb4+hdwt#Z3NkO4@bAgEJ|u1*sj>0)5Sp35mbImN7es^ z!1f*Q@5O0TK24eyrmClTFMvm|Wc;+$9ffoMFgA)M8K2ECP|RnOf;e_wC+lu>cyoEl zjGK?D9Rpzutw4)od0vg{u%A`mjL9f^PgIyuTXHO4<~w@4R+B^2Wsk)l7Yfb6-yE-1 zt_xlw-o0yS^aH%!ZM;$m|$tUg(0dZMsSRhDV!EQSa?8z{54+$J=sPx@TZOuW>v z@pzMw3h1T8ksDfC7}9@ByY4IB$Gydaa&c;=Ts_S#!tabW$jYGqCpsx5n?B5lLp+*} zbZ%BW20pcujg7{~j!gYqn;$AaJA+QTii!T`W}mXPUT)=Sp|S*_p=701Q6(BRuR8Q>qMgL!cN8)gA3Z^$Mrt*on!eIl1+bn6 z=~eQrvqRJ(7Q?rpK1C^bH5tNjTG=N!$TtRmv&#>@MYen!AaygQ{vU9u42sm{JBWnnyBl%jH{KM zO=|RnrlHM)*N=(JtN&N_ zVBtEj`4JaN_B8W$SpP+e8p#5V_(TpWp^i#2!juMybP$7v7hEFiho(uXc_;gu9FuW4 zWfIP&dCC+Ng-_{B^pgYJw1uOlDUG~s5JjKi&o@J>(__NajL076FjmGee+}&dG!b|{ z$uGt=;?w*e*iUSpgN!A(_yz4+9$f$Dj|2hO@WCY{n`i?#DR8a#zxj_s=l{+=?lLc| ze-rXc@#RA)2?FSL8xG`;99gijPJ;2biI9H>op%=V#Q6B5R51f}b&za|xR#^DkOe!t zxZK}I;p5>ATk(`4980ds9x9+{E+V449aPCT`1cA|fIiTiZff?}#jB0}8TW!rM2@!S~wIE2g`s zNDeNIY_SgXR~5r7BErI^0aXO`@?yb;Uh8dUZc7vZ`?RfNiz=NK*oJpYBmRf(d&+QTnzaC&Ou z5gDwbA?`@`R~h#qb3fze7Zmf}6z)KM3|=oNhCk67vpFSs&Nt|HReUL3ekOX_hK+yQ zP07O2Jw4#+%1~)4ff({qPH=t_!=SBXZ`iPjShg%Z|5dlbX^Mr#7yZWsRtOu=bQBJl zC_+WclMAnvNtKP$t7K7$@SD=K5zC%*-h6i*K#ACSKq?y|9(qTHk|TErnUq& zb6{JjGgf~GMd=6cg>GbjDx$*pIZ9QCjJW@CEsuJjUVFe@zVCjDlOmoJ>zsM;Yrikh zzbHhlv6UDymk@`q|C%<%m@EaBH*6JG>JN)pVzZVE|Bv(i{M?8vtuG&4wU3u|NOgV2 zryXyAccJ3E*8qOGQ}^WpJTHymLR4;DI=nvM*b-i7lr%9}sx@)Yg0oG*kJy9-i%&JOM2 zzvac>sC!i8MGgB(G0gGr4Aaso;Svfy$1gRgV@AF-=0!Y?IsH{F_dzn1>}u&M*N9_2 zT}##CXKZE<@m_PnQeRj?EJX`O%rtO8huhjf1Wku6F39FLeuPqTV;6@NlsWZf zTs1vA;m8mpWOGj%OVc^r+!DO!7|8Whf3#ij%h}>(5>n}@LI!VP%C7F!CjeQ=z{{b? zm{saz>rm0Mw~U_~Z2OpVZlgT}Gu?!=E6;2J#Ghl(mpZ?hAiY`n&x;3 z=);r7+5j2^)I_musCd%;qO>l2?xqP=6uIaNZ8$^nWZHm1Q=1<`jbm=L*t+2Ey`V~> zoJg<5+>OuS=Aq0&+6Maz_;>Q3Z@p>~Tq?Do*dii$xM*o5P;^v#nM~W zu739pVva$%*QQlN3!Vx2HMKiljw*k&W|I=uy4pX!(Er7x>^3=#9EGQ)SyNuE%d0iB zVULiqp1wOy<7U&eADpdd?eyJ_jqa%vU^NM4kvVCP-}|lYQGr+wN#EP;)1Ru?PqFWL z&Lg=OHM%R}RPAE-gI}gSmpG)qdKev4HU*z=7wr7fi){MPvkZkeQN&#HN;?H&X@PQ7 zWAn;v_k(0-zEcNOZ$o3uL;F5i*YWpjk**o3-f>68cdrNeoQ_r!OC_k&AkN>g+@*_| zeHRve3m- zNa(C7YN01~G?;2D5`x zrk4-?Ul5>EqI-`>wfw6hLyuHEJtzInk$;OaKZt5?ZJ?#} zPxpUlo*yP>NTLc(Eyd8An@0B`i<-lJHN+wHO~G!NN_bQh&$A;E!Utd;3*T+Xj64f} zzf#H+lJ4K?e4JXNt{%`gxV6QB+w_E}Fp}EPFrAVxX7L5h(A7qe%m_{Q!cH+=I4-gh zjf_ae^Y*9N@bJ$1nMf_xK|$xkgu-#vGU&&6!=iDDc!rdBS6#X$9`$@mW8pX0SAI-d z_{b|A+8Cdz{%JrwtvOYFVLo<5dhXHc@35Mls#=ZP(SFWWj-X8|2;x^zw7wdfNZBJdq+iMEyR0dE&u2X{ z--kSBXe||84UOs!*}r@Ioz2{$rECc*M`gr^sh2}?v=*}zKcY{e9#Kixvf}SNvDY25 zz@7iv;Eeo9U8vA9tL?Y=k^ZehTm@Tm@S$L}F)N68r5;(aDVlqPdukTUF4d ze}Zi#JB;MTc`vo<)s17dDB~>$g;U$<<^(q$4bpRUZsfOfYq+a41V@Bf6&L-Cm9cwe z_br|FkivTC!mR6Ld0ceYDxpQ{;%r{N6;`k=c6A`!yotZ@Q1t54q^z6vVA@op^Kl;L z@|TFH{TE-2;X5I3YBra3z*?>OS$V#4GDM1IH2CtWNAbw!cuQb#Z`Lp?B8kZQmudvW z2`{ctH(7V(F1uqRJ^Z7ce*y>)CsJNXcIbxv`usYZZh>|ZyqI0uHUWip!z-FU)bT&VZ`)(Hg>{pfP z49jAk;?S7wUEIyFt9_d~m&=*eOBkbVnb57jz+CTa##Em$x_(FH3 zC#)f`{|_Wm1ZwU!e6Ex_7fl)#I_^t>)VmOhs_Y0UIvV!B(^K=2^}_M-HVQQ)~x5*ld*LHm!lG1I_-fsihuuBtt`N`Jw^5s&lrM_CJd zHB0%_$Pnz;m$&SqdIJsT>lC#*5kI-7Be(`-BK`fK)fJx}*u{{B%07g?cRoR`Y$FB_ zyVI%3R|(3$6O;#M?3`$}JTN-hD%WWELCsj=auYHs&F;j!HRn>y&$}&R)VlJ}z;ZUM zet!}W?HSSINpv5|MZh@!bDA*oOcr5i8mqsccfN6RN7D07Xs$0mDPfoF-UeL={;{un zm)6rJ%*U&R9oPb$rtpn-v(W|GJJ5$xDm#-HrB>1D0j>JH6Q^hJME6vDs_~u=t8Cu3 ztvWhH$NQ#|w|H&fS78Acd}Z1@3FHX<7V!%K8lj?S#A-W#McMn7A_Hs}k5kk!NpWe} zyf0QTe#@w9n{tF!5f+Ls%o61|t+|oLBc@(lf^C1d`<5v>-amL78mpN`r+W4@I?CXztK1m>1l5qx;3-*45Bar|nK}H0 z9hKok4HTQgnwHz=&Pj@UllJRz#-aw=L~=#lvT6*7nA2W{tDfKU;(79>!6+9Mk6T>l z4w5oVCH+^{T_zzjymW#B?0*L0c+4yLOgnauBZ~XFIBa_3s-YQ-#Jq@ro{re93Cmr> zDk~NQ_1Mj&31nE?%w7D z{?;WgGs!;X(B!EZ$N+*XJ{8TDRjp*)FP?$xACb2p>y>e%dC}3zfMIoTC~JEQ7)rp` zGRB5IT-~Rr9zUWC-~@KAb$O zUVU*Mr*7{>LVo}6E!xb9pJh}L<};?>V&O_&ex%PgHT9^afSB%`$`DXhuW+pw}B`zs`JI? zVJlo5JiL4N_{eYz0Qow1ep}*)Zs~)NTfPD}A#NfG<{HoAmGW(K*VrV6z->z3nd>wg z!lx|(1)%jlxB5RgfxGS3KK+oF*#9-N`xdl;W)At401RC-R_<&~9(i+eQW{ryTs4vis zMn>|IM{1>_D#k@1zc8W9;b4UV(`mjGwu(UU_}AmFucZG);FJ$~`qc9K2UviOe5oc2 zVOUl{Dk`PZ0qO)athPkixklvzF*Y^V{X>0xe4rmgYAZWL{{I*H)BVdQ{8K#0dA_m@ z_bAbAI7rNT-YDeNiKBcXbc{ymi88hbFhb|25rCkHXKrjx$+7vL1Ad=V65IPOBpkX` z=u^QeN&BP2=mumP6ZPhDustV82r%|<02V`~n$+>s9f}9(H;RgZqsa!k^;Tz`#@_!V@SWl7`AO2UHMlFRn@w|i7`xnH8y330JFs_e zt?Bn(%fMXV;VV1@k>K{~WFTqo)4wAX$2hG+Q-MX-oLaClV9ogH<)N2dX!%yd2GR1I z-*!xr(M$`zY+bRg>eRZ8PAY5f+ieE9=?>mo$6|#D#QZN2ZNpV2NL7;ptwKLr(38*y zTTfH0rjO5l16NT)RMV*fzKRmuY{=-aEodYs@#@=l7vaIGI2ySOyJ`(||K@!L$LKx8 zTp(mVZG3A$3L5=}IX_0V=Xhz2=|dLzCjN^M^Y~|)({7t#^=j{0GlFiH$2v}4Z5l_b z8JTFlCT7amLb=SYu1V3P0d>DK0QdHlvTr?5>$#(LmCywr^63$}*r{kEC;IIze3IxD z?SFVcMj9f8>%7{Vo^iFit+2c=W0bsUFZiY9Z5wvUUaIxH+=}-?+j1GG!4dBLtG9Uu zwnG2%gVEGpcRN`23p)|rV-uMLnv3YJflA-Y14Hy~E(J># z^|z^x#}U~O2+!|gP!9p@Jw=9q^DU8zv~>3mdeOS@%^2&!)>)Qn!w}o z#FLWG%8y+fbzgHBu}Lx{<8v4qthmA(IX>eL_ae;1>dfpbHm*?VRKz8;o1^r9t~T|G z6RGP_@nTqXbX>Q4P&<#x3Tc`=56+RpYVdF0wg-u%ywtb-&ByabV@(=+uDSThv+`RI zCq3(ynK0(N(9R7}zozC~odsvP=YB|$p@^m@m{(8{j?fXuATf*6f_3kK1lD5bewOIE zz*i*|Vn8M~H@MPY+h>+6;$3;zCm*$(W67?Q&`evLW_9^B{rrXVTt%87MdgTiuR^r{ zzA{I2n0h=St%AbT_rm6(v?t*u`k67o zp$S#_uc zSRBtJyee{+!B4M|F>(-AxlRX6QVM$wQd5=C(p^k{=wVI%C9BMm%e>HrMaFm2{r&sPgd6`*Okbip?LK)|Vd+yAL+SA0#AiPxD+H}K|TCf;4F+R$M>fplFo%AwfZU*+%?Rx(}aP(6aO1*jb^e;{`Koh z-BOXEfkqK#iZ+0e;%({41>X_cwIgY zTiI>Av)=`<>Rn2F7`p{(}r=-M}q>#fL zVzl>95P@zxdEL)LH}6rFJr7+y2Vq)%_mwP|MB#kxY?6i zfaD*u;pH8KD+Ut+{Pgmo&z_00hcKqkjGW&g^>uDmw;FrL3zCSgw=Z}y-pBs~aePtB zK|wdcfZN;KbKbHUP_M-Q$T4;iY$8^E1X(0`Qsb#6$()$cWJZ?v0{W3(F3qtkdGSi!Q5xglXJ{jg{3*$Ks_4fLn3N z8fAWz|B@$zf1R{h6M}+9&+gnIiMaC~2pRx3Gvy)g0L2=wg7C0zJqL;WS}_TN63ya{ xzh9_PH?G0u|4|L_!yXjy{+}V^|0V`F#N4bD{Yiq?*>?S>a#BjrvR7||{x7F^=dl0) diff --git a/docs/source/io_formats/plots.rst b/docs/source/io_formats/plots.rst index 04d5720c8..c1fa78330 100644 --- a/docs/source/io_formats/plots.rst +++ b/docs/source/io_formats/plots.rst @@ -71,9 +71,9 @@ sub-elements: the PNG file format. The "voxel" plot type produces a binary datafile containing voxel grid positioning and the cell or material (specified by the ``color`` tag) at the center of each voxel. Voxel plot files can be - processed into VTK files using the :ref:`scripts_voxel` script provided with - OpenMC and subsequently viewed with a 3D viewer such as VISIT or Paraview. - See the :ref:`io_voxel` for information about the datafile structure. + processed into VTK files using the :func:`openmc.voxel_to_vtk` function and + subsequently viewed with a 3D viewer such as VISIT or Paraview. See the + :ref:`io_voxel` for information about the datafile structure. .. note:: High-resolution voxel files produced by OpenMC can be quite large, but the equivalent VTK files will be significantly smaller. @@ -152,17 +152,17 @@ attributes or sub-elements. These are not used in "voxel" plots: *Default*: 255 255 255 (white) :show_overlaps: - Indicates whether overlapping regions of different cells are shown. + Indicates whether overlapping regions of different cells are shown. *Default*: None :overlap_color: - Specifies the RGB color of overlapping regions of different cells. Does not - do anything if ``show_overlaps`` is "false" or not specified. Should be 3 + Specifies the RGB color of overlapping regions of different cells. Does not + do anything if ``show_overlaps`` is "false" or not specified. Should be 3 integers separated by spaces. *Default*: 255 0 0 (red) - + :meshlines: The ``meshlines`` sub-element allows for plotting the boundaries of a regular mesh on top of a plot. Only one ``meshlines`` element is allowed per diff --git a/docs/source/usersguide/plots.rst b/docs/source/usersguide/plots.rst index 2d588519c..d453ea453 100644 --- a/docs/source/usersguide/plots.rst +++ b/docs/source/usersguide/plots.rst @@ -111,11 +111,11 @@ The voxel plot data is written to an :ref:`HDF5 file `. The voxel file can subsequently be converted into a standard mesh format that can be viewed in `ParaView `_, `VisIt `_, etc. This typically -will compress the size of the file significantly. The provided -:ref:`scripts_voxel` script can convert the HDF5 voxel file to VTK formats. Once -processed into a standard 3D file format, colors and masks can be defined using -the stored ID numbers to better explore the geometry. The process for doing this -will depend on the 3D viewer, but should be straightforward. +will compress the size of the file significantly. The +:func:`openmc.voxel_to_vtk` function can convert the HDF5 voxel file to VTK +formats. Once processed into a standard 3D file format, colors and masks can be +defined using the stored ID numbers to better explore the geometry. The process +for doing this will depend on the 3D viewer, but should be straightforward. .. note:: 3D voxel plotting can be very computer intensive for the viewing program (Visit, ParaView, etc.) if the number of voxels is large (>10 diff --git a/docs/source/usersguide/processing.rst b/docs/source/usersguide/processing.rst index 3103b7b7c..10944b5e2 100644 --- a/docs/source/usersguide/processing.rst +++ b/docs/source/usersguide/processing.rst @@ -41,12 +41,9 @@ Plotting in 2D -------------- The `example notebook`_ also demonstrates how to plot a structured mesh tally in -two dimensions using the Python API. One can also use the :ref:`scripts_plot` -script which provides an interactive GUI to explore and plot structured mesh -tallies for any scores and filter bins. - -.. image:: ../_images/plotmeshtally.png - :width: 400px +two dimensions using the Python API. One can also use the `openmc-plotter +`_ application that provides an +interactive GUI to explore and plot a much wider variety of tallies. .. _usersguide_track: @@ -81,7 +78,7 @@ of three, e.g., if we wanted particles 3 and 4 from batch 1 and generation 2:: After running OpenMC, the working directory will contain a file of the form "track_(batch #)_(generation #)_(particle #).h5" for each particle tracked. These track files can be converted into VTK poly data files with the -:ref:`scripts_track` script. +:class:`openmc.Tracks` class. ---------------------- Source Site Processing diff --git a/docs/source/usersguide/scripts.rst b/docs/source/usersguide/scripts.rst index 78ee6f775..0879d63ef 100644 --- a/docs/source/usersguide/scripts.rst +++ b/docs/source/usersguide/scripts.rst @@ -53,142 +53,3 @@ flags: .. note:: If you're using the Python API, :func:`openmc.run` is equivalent to running ``openmc`` from the command line. - -.. _scripts_ace: - ----------------------- -``openmc-ace-to-hdf5`` ----------------------- - -This script can be used to create HDF5 nuclear data libraries used by OpenMC if -you have existing ACE files. There are four different ways you can specify ACE -libraries that are to be converted: - -1. List each ACE library as a positional argument. This is very useful in - conjunction with the usual shell utilities (``ls``, ``find``, etc.). -2. Use the ``--xml`` option to specify a pre-v0.9 cross_sections.xml file. -3. Use the ``--xsdir`` option to specify a MCNP xsdir file. -4. Use the ``--xsdata`` option to specify a Serpent xsdata file. - -The script does not use any extra information from cross_sections.xml/ xsdir/ -xsdata files to determine whether the nuclide is metastable. Instead, the -``--metastable`` argument can be used to specify whether the ZAID naming convention -follows the NNDC data convention (1000*Z + A + 300 + 100*m), or the MCNP data -convention (essentially the same as NNDC, except that the first metastable state -of Am242 is 95242 and the ground state is 95642). - -The optional ``--fission_energy_release`` argument will accept an HDF5 file -containing a library of fission energy release (ENDF MF=1 MT=458) data. A -library built from ENDF/B-VII.1 data is released with OpenMC and can be found at -openmc/data/fission_Q_data_endb71.h5. This data is necessary for -'fission-q-prompt' and 'fission-q-recoverable' tallies, but is not needed -otherwise. - --h, --help show help message and exit - --d DESTINATION, --destination DESTINATION - Directory to create new library in - --m META, --metastable META - How to interpret ZAIDs for metastable nuclides. META - can be either 'nndc' or 'mcnp'. (default: nndc) - ---xml XML Old-style cross_sections.xml that lists ACE libraries - ---xsdir XSDIR MCNP xsdir file that lists ACE libraries - ---xsdata XSDATA Serpent xsdata file that lists ACE libraries - ---fission_energy_release FISSION_ENERGY_RELEASE - HDF5 file containing fission energy release data - -.. _scripts_plot: - --------------------------- -``openmc-plot-mesh-tally`` --------------------------- - -``openmc-plot-mesh-tally`` provides a graphical user interface for plotting mesh -tallies. The path to the statepoint file can be provided as an optional arugment -(if omitted, a file dialog will be presented). - -.. _scripts_track_combine: - ------------------------- -``openmc-track-combine`` ------------------------- - -This script combines multiple HDF5 :ref:`particle track files -` into a single HDF5 particle track file. The filenames of the -particle track files should be given as posititional arguments. The output -filename can also be changed with the ``-o`` flag: - --o OUT, --out OUT Output HDF5 particle track file - -.. _scripts_track: - ------------------------ -``openmc-track-to-vtk`` ------------------------ - -This script converts HDF5 :ref:`particle track files ` to VTK -poly data that can be viewed with ParaView or VisIt. The filenames of the -particle track files should be given as posititional arguments. The output -filename can also be changed with the ``-o`` flag: - --o OUT, --out OUT Output VTK poly filename - ------------------------- -``openmc-update-inputs`` ------------------------- - -If you have existing XML files that worked in a previous version of OpenMC that -no longer work with the current version, you can try to update these files using -``openmc-update-inputs``. If any of the given files do not match the most -up-to-date formatting, then they will be automatically rewritten. The old -out-of-date files will not be deleted; they will be moved to a new file with -'.original' appended to their name. - -Formatting changes that will be made: - -geometry.xml - Lattices containing 'outside' attributes/tags will be replaced with lattices - containing 'outer' attributes, and the appropriate cells/universes will be - added. Any 'surfaces' attributes/elements on a cell will be renamed 'region'. - -materials.xml - Nuclide names will be changed from ACE aliases (e.g., Am-242m) to HDF5/GNDS - names (e.g., Am242_m1). Thermal scattering table names will be changed from - ACE aliases (e.g., HH2O) to HDF5/GNDS names (e.g., c_H_in_H2O). - ----------------------- -``openmc-update-mgxs`` ----------------------- - -This script updates OpenMC's deprecated multi-group cross section XML files to -the latest HDF5-based format. - --i IN, --input IN Input XML file --o OUT, --output OUT Output file in HDF5 format - -.. _scripts_voxel: - ---------------------------- -``openmc-voxel-to-vtk`` ---------------------------- - -When OpenMC generates :ref:`voxel plots `, they are in an -:ref:`HDF5 format ` that is not terribly useful by itself. The -``openmc-voxel-to-vtk`` script converts a voxel HDF5 file to a `VTK -`_ file. To run this script, you will need to have the VTK -Python bindings installed. To convert a voxel file, simply provide the path to -the file: - -.. code-block:: sh - - openmc-voxel-to-vtk voxel_1.h5 - -The ``openmc-voxel-to-vtk`` script also takes the following optional -command-line arguments: - --o, --output Path to output VTK file diff --git a/docs/source/usersguide/settings.rst b/docs/source/usersguide/settings.rst index ca11d6487..1b2d4bc1a 100644 --- a/docs/source/usersguide/settings.rst +++ b/docs/source/usersguide/settings.rst @@ -751,11 +751,10 @@ instance, whereas the :meth:`openmc.Track.filter` method returns a new with more than one process, a separate track file will be written for each MPI process with the filename ``tracks_p#.h5`` where # is the rank of the corresponding process. Multiple track files can be - combined with the :ref:`scripts_track_combine` script: + combined with the :meth:`openmc.Tracks.combine` method:: - .. code-block:: sh - - openmc-track-combine tracks_p*.h5 --out tracks.h5 + track_files = [f"tracks_p{rank}.h5" for rank in range(32)] + openmc.Tracks.combine(track_files, "tracks.h5") ----------------------- Restarting a Simulation diff --git a/pyproject.toml b/pyproject.toml index e4e8472f1..1f8de10e3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,19 +59,10 @@ Repository = "https://github.com/openmc-dev/openmc" Issues = "https://github.com/openmc-dev/openmc/issues" [tool.setuptools.packages.find] -include = ['openmc*', 'scripts*'] +include = ['openmc*'] exclude = ['tests*'] [tool.setuptools.package-data] "openmc.data.effective_dose" = ["**/*.txt"] "openmc.data" = ["*.txt", "*.DAT", "*.json", "*.h5"] "openmc.lib" = ["libopenmc.dylib", "libopenmc.so"] - -[project.scripts] -openmc-ace-to-hdf5 = "scripts.openmc_ace_to_hdf5:main" -openmc-plot-mesh-tally = "scripts.openmc_plot_mesh_tally:main" -openmc-track-combine = "scripts.openmc_track_combine:main" -openmc-track-to-vtk = "scripts.openmc_track_to_vtk:main" -openmc-update-inputs = "scripts.openmc_update_inputs:main" -openmc-update-mgxs = "scripts.openmc_update_mgxs:main" -openmc-voxel-to-vtk = "scripts.openmc_voxel_to_vtk:main" diff --git a/scripts/openmc-ace-to-hdf5 b/scripts/openmc-ace-to-hdf5 deleted file mode 100755 index 66ae7e2a9..000000000 --- a/scripts/openmc-ace-to-hdf5 +++ /dev/null @@ -1,156 +0,0 @@ -#!/usr/bin/env python3 - -"""This script can be used to create HDF5 nuclear data libraries used by -OpenMC. There are four different ways you can specify ACE libraries that are to -be converted: - -1. List each ACE library as a positional argument. This is very useful in - conjunction with the usual shell utilities (ls, find, etc.). -2. Use the --xsdir option to specify a MCNP xsdir file. -3. Use the --xsdata option to specify a Serpent xsdata file. - -The script does not use any extra information from xsdir/xsdata files to -determine whether the nuclide is metastable. Instead, the --metastable argument -can be used to specify whether the ZAID naming convention follows the NNDC data -convention (1000*Z + A + 300 + 100*m), or the MCNP data convention (essentially -the same as NNDC, except that the first metastable state of Am242 is 95242 and -the ground state is 95642). - -""" - -import argparse -from functools import partial -import os -from pathlib import Path -import warnings - -import openmc.data -from openmc.data.ace import TableType - - -def ace_to_hdf5(destination, xsdir, xsdata, libraries, metastable, libver): - - if not destination.is_dir(): - destination.mkdir(parents=True, exist_ok=True) - - ace_libraries = [] - if xsdir is not None: - ace_libraries.extend(openmc.data.ace.get_libraries_from_xsdir(xsdir)) - elif xsdata is not None: - ace_libraries.extend(openmc.data.ace.get_libraries_from_xsdata(xsdata)) - else: - ace_libraries = [Path(lib) for lib in libraries] - - converted = {} - library = openmc.data.DataLibrary() - - for path in ace_libraries: - # Check that ACE library exists - if not os.path.exists(path): - warnings.warn(f"ACE library '{path}' does not exist.") - continue - - lib = openmc.data.ace.Library(path) - for table in lib.tables: - # Check type of the ACE table and determine appropriate class / - # conversion function - if table.data_type == TableType.NEUTRON_CONTINUOUS: - name = table.zaid - cls = openmc.data.IncidentNeutron - converter = partial(cls.from_ace, metastable_scheme=metastable) - elif table.data_type == TableType.THERMAL_SCATTERING: - # Adjust name to be the new thermal scattering name - name = openmc.data.get_thermal_name(table.zaid) - cls = openmc.data.ThermalScattering - converter = cls.from_ace - else: - print(f"Can't convert ACE table {table.name}") - continue - - if name not in converted: - try: - data = converter(table) - except Exception as e: - print(f"Failed to convert {table.name}: {e}") - continue - - print(f"Converting {table.name} (ACE) to {data.name} (HDF5)") - - # Determine output filename - outfile = destination / (data.name.replace(".", "_") + ".h5") - data.export_to_hdf5(outfile, "w", libver=libver) - - # Register with library - library.register_file(outfile) - - # Add nuclide to list - converted[name] = outfile - else: - # Read existing HDF5 file - data = cls.from_hdf5(converted[name]) - - # Add data for new temperature - try: - print(f"Converting {table.name} (ACE) to {data.name} (HDF5)") - if table.data_type == TableType.NEUTRON_CONTINUOUS: - data.add_temperature_from_ace(table, metastable) - else: - data.add_temperature_from_ace(table) - except Exception as e: - print(f"Failed to convert {table.name}: {e}") - continue - - # Re-export - data.export_to_hdf5(converted[name], "w", libver=libver) - - # Write cross_sections.xml - library.export_to_xml(destination / "cross_sections.xml") - - -if __name__ == "__main__": - - class CustomFormatter( - argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter - ): - pass - - parser = argparse.ArgumentParser( - description=__doc__, formatter_class=CustomFormatter - ) - parser.add_argument("libraries", nargs="*", help="ACE libraries to convert to HDF5") - parser.add_argument( - "-d", - "--destination", - type=Path, - default=Path.cwd(), - help="Directory to create new library in", - ) - parser.add_argument( - "-m", - "--metastable", - choices=["mcnp", "nndc"], - default="nndc", - help="How to interpret ZAIDs for metastable nuclides", - ) - parser.add_argument("--xsdir", help="MCNP xsdir file that lists " "ACE libraries") - parser.add_argument( - "--xsdata", help="Serpent xsdata file that lists " "ACE libraries" - ) - parser.add_argument( - "--libver", - choices=["earliest", "latest"], - default="earliest", - help="Output HDF5 versioning. Use " - "'earliest' for backwards compatibility or 'latest' " - "for performance", - ) - args = parser.parse_args() - - ace_to_hdf5( - destination=args.destination, - xsdir=args.xsdir, - xsdata=args.xsdata, - libraries=args.libraries, - metastable=args.metastable, - libver=args.libver, - ) diff --git a/scripts/openmc-plot-mesh-tally b/scripts/openmc-plot-mesh-tally deleted file mode 100755 index 2a4fcd743..000000000 --- a/scripts/openmc-plot-mesh-tally +++ /dev/null @@ -1,344 +0,0 @@ -#!/usr/bin/env python3 - -"""Python script to plot tally data generated by OpenMC.""" - - -import os -import sys -import argparse -import tkinter as tk -import tkinter.filedialog as filedialog -import tkinter.font as font -import tkinter.messagebox as messagebox -import tkinter.ttk as ttk - -import matplotlib -matplotlib.use("TkAgg") -from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg -from matplotlib.backends.backend_tkagg import NavigationToolbar2Tk -from matplotlib.figure import Figure -import matplotlib.pyplot as plt -import numpy as np - -from openmc import StatePoint, MeshFilter, UnstructuredMesh - -_COMBOBOX_SELECTED = '<>' - - -def mesh_filter_check(filter): - """ - Check that the filter is a usable mesh filter - """ - return isinstance(filter, MeshFilter) and not isinstance(filter.mesh, UnstructuredMesh) - - -class MeshPlotter(tk.Frame): - def __init__(self, parent, filename): - super().__init__(parent) - - self.labels = { - 'Cell': 'Cell:', - 'Cellborn': 'Cell born:', - 'Surface': 'Surface:', - 'Material': 'Material:', - 'Universe': 'Universe:', - 'Energy': 'Energy in:', - 'Energyout': 'Energy out:' - } - - self.filterBoxes = {} - - # Read data from source or leakage fraction file - self.get_file_data(filename) - - # Set up top-level window - top = self.winfo_toplevel() - top.title('Mesh Tally Plotter: ' + filename) - top.rowconfigure(0, weight=1) - top.columnconfigure(0, weight=1) - self.grid(sticky=tk.W+tk.N) - - # Create widgets and draw to screen - self.create_widgets() - self.update() - - def create_widgets(self): - figureFrame = tk.Frame(self) - figureFrame.grid(row=0, column=0) - - # Create the Figure and Canvas - self.dpi = 100 - self.fig = Figure((5.0, 5.0), dpi=self.dpi) - self.canvas = FigureCanvasTkAgg(self.fig, master=figureFrame) - self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1) - - # Create the navigation toolbar, tied to the canvas - self.mpl_toolbar = NavigationToolbar2Tk(self.canvas, figureFrame) - self.mpl_toolbar.update() - self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1) - - # Create frame for comboboxes - self.selectFrame = tk.Frame(self) - self.selectFrame.grid(row=1, column=0, sticky=tk.W+tk.E) - - # Tally selection - labelTally = tk.Label(self.selectFrame, text='Tally:') - labelTally.grid(row=0, column=0, sticky=tk.W) - self.tallyBox = ttk.Combobox(self.selectFrame, state='readonly') - self.tallyBox['values'] = [self.datafile.tallies[i].id - for i in self.meshTallies] - self.tallyBox.current(0) - self.tallyBox.grid(row=0, column=1, sticky=tk.W+tk.E) - self.tallyBox.bind(_COMBOBOX_SELECTED, self.update) - - # Planar basis selection - labelBasis = tk.Label(self.selectFrame, text='Basis:') - labelBasis.grid(row=1, column=0, sticky=tk.W) - self.basisBox = ttk.Combobox(self.selectFrame, state='readonly') - self.basisBox['values'] = ('xy', 'yz', 'xz') - self.basisBox.current(0) - self.basisBox.grid(row=1, column=1, sticky=tk.W+tk.E) - self.basisBox.bind(_COMBOBOX_SELECTED, self.update) - - # Axial level - labelAxial = tk.Label(self.selectFrame, text='Axial level:') - labelAxial.grid(row=2, column=0, sticky=tk.W) - self.axialBox = ttk.Combobox(self.selectFrame, state='readonly') - self.axialBox.grid(row=2, column=1, sticky=tk.W+tk.E) - self.axialBox.bind(_COMBOBOX_SELECTED, self.redraw) - - # Option for mean/uncertainty - labelMean = tk.Label(self.selectFrame, text='Mean/Uncertainty:') - labelMean.grid(row=3, column=0, sticky=tk.W) - self.meanBox = ttk.Combobox(self.selectFrame, state='readonly') - self.meanBox['values'] = ('Mean', 'Absolute uncertainty', - 'Relative uncertainty') - self.meanBox.current(0) - self.meanBox.grid(row=3, column=1, sticky=tk.W+tk.E) - self.meanBox.bind(_COMBOBOX_SELECTED, self.update) - - # Scores - labelScore = tk.Label(self.selectFrame, text='Score:') - labelScore.grid(row=4, column=0, sticky=tk.W) - self.scoreBox = ttk.Combobox(self.selectFrame, state='readonly') - self.scoreBox.grid(row=4, column=1, sticky=tk.W+tk.E) - self.scoreBox.bind(_COMBOBOX_SELECTED, self.redraw) - - # Filter label - boldfont = font.Font(weight='bold') - labelFilters = tk.Label(self.selectFrame, text='Filters:', - font=boldfont) - labelFilters.grid(row=5, column=0, sticky=tk.W) - - def update(self, event=None): - widget = event.widget if event else None - - tally_id = self.meshTallies[self.tallyBox.current()] - selectedTally = self.datafile.tallies[tally_id] - - # Get mesh for selected tally - self.mesh = selectedTally.find_filter(MeshFilter).mesh - - # Get mesh dimensions - if len(self.mesh.dimension) == 2: - self.nx, self.ny = self.mesh.dimension - self.nz = 1 - else: - self.nx, self.ny, self.nz = self.mesh.dimension - - # Repopulate comboboxes baesd on current basis selection - text = self.basisBox.get() - if text == 'xy': - self.axialBox['values'] = [str(i+1) for i in range(self.nz)] - elif text == 'yz': - self.axialBox['values'] = [str(i+1) for i in range(self.nx)] - else: - self.axialBox['values'] = [str(i+1) for i in range(self.ny)] - self.axialBox.current(0) - - # If update() was called by a change in the basis combobox, we don't - # need to repopulate the filters - if widget == self.basisBox: - self.redraw() - return - - # Update scores - self.scoreBox['values'] = selectedTally.scores - self.scoreBox.current(0) - - # Remove any filter labels/comboboxes that exist - for row in range(6, self.selectFrame.grid_size()[1]): - for w in self.selectFrame.grid_slaves(row=row): - w.grid_forget() - w.destroy() - - # create a label/combobox for each filter in selected tally - count = 0 - for f in selectedTally.filters: - filterType = f.short_name - if filterType == 'Mesh': - continue - count += 1 - - # Create label and combobox for this filter - label = tk.Label(self.selectFrame, text=self.labels[filterType]) - label.grid(row=count+6, column=0, sticky=tk.W) - combobox = ttk.Combobox(self.selectFrame, state='readonly') - self.filterBoxes[filterType] = combobox - - # Set combobox items - if filterType in ['Energy', 'Energyout']: - combobox['values'] = ['{} to {}'.format(*ebin) - for ebin in f.bins] - else: - combobox['values'] = [str(i) for i in f.bins] - - combobox.current(0) - combobox.grid(row=count+6, column=1, sticky=tk.W+tk.E) - combobox.bind(_COMBOBOX_SELECTED, self.redraw) - - # If There are no filters, leave a 'None available' message - if count == 0: - count += 1 - label = tk.Label(self.selectFrame, text="None Available") - label.grid(row=count+6, column=0, sticky=tk.W) - - self.redraw() - - def redraw(self, event=None): - basis = self.basisBox.current() + 1 - axial_level = self.axialBox.current() + 1 - mbvalue = self.meanBox.get() - - # Get selected tally - tally_id = self.meshTallies[self.tallyBox.current()] - selectedTally = self.datafile.tallies[tally_id] - - # Create spec_list - spec_list = [] - for f in selectedTally.filters: - if f.short_name == 'Mesh': - mesh_filter = f - continue - elif f.short_name in ['Energy', 'Energyout']: - index = self.filterBoxes[f.short_name].current() - ebin = f.bins[index] - spec_list.append((type(f), (ebin,))) - else: - index = self.filterBoxes[f.short_name].current() - spec_list.append((type(f), (index,))) - - dims = (self.nx, self.ny, self.nz) - - text = self.basisBox.get() - if text == 'xy': - h_ind = 0 - v_ind = 1 - elif text == 'yz': - h_ind = 1 - v_ind = 2 - else: - h_ind = 0 - v_ind = 2 - - axial_ind = 3 - (h_ind + v_ind) - dims = (dims[h_ind], dims[v_ind]) - - mesh_dim = len(self.mesh.dimension) - if mesh_dim == 3: - mesh_indices = [0,0,0] - else: - mesh_indices = [0,0] - - matrix = np.zeros(dims) - for i in range(dims[0]): - for j in range(dims[1]): - if mesh_dim == 3: - mesh_indices[h_ind] = i + 1 - mesh_indices[v_ind] = j + 1 - mesh_indices[axial_ind] = axial_level - else: - mesh_indices[0] = i + 1 - mesh_indices[1] = j + 1 - filters, filter_bins = zip(*spec_list + [ - (type(mesh_filter), (tuple(mesh_indices),))]) - mean = selectedTally.get_values( - [self.scoreBox.get()], filters, filter_bins) - stdev = selectedTally.get_values( - [self.scoreBox.get()], filters, filter_bins, - value='std_dev') - if mbvalue == 'Mean': - matrix[i, j] = mean - elif mbvalue == 'Absolute uncertainty': - matrix[i, j] = stdev - else: - if mean > 0.: - matrix[i, j] = stdev/mean - else: - matrix[i, j] = 0. - - # Clear the figure - self.fig.clear() - - # Make figure, set up color bar - self.axes = self.fig.add_subplot(111) - cax = self.axes.imshow(matrix.transpose(), vmin=0.0, vmax=matrix.max(), - interpolation='none', origin='lower') - self.fig.colorbar(cax) - - self.axes.set_xticks([]) - self.axes.set_yticks([]) - self.axes.set_aspect('equal') - - # Draw canvas - self.canvas.draw() - - def get_file_data(self, filename): - # Create StatePoint object and read in data - self.datafile = StatePoint(filename) - - meshes = self.datafile.meshes - if any(isinstance(m, UnstructuredMesh) for m in meshes.values()): - warn_msg = "Unstructured meshes are present in the" \ - " statepoint file but are not currently" \ - " supported by this script" - messagebox.showwarning("Unstructured Meshes", message=warn_msg) - - # Find which tallies are mesh tallies - self.meshTallies = [] - for itally, tally in self.datafile.tallies.items(): - if any([mesh_filter_check(f) for f in tally.filters]): - self.meshTallies.append(itally) - - if not self.meshTallies: - messagebox.showerror("Invalid StatePoint File", - "File does not contain mesh tallies!") - sys.exit(1) - - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('statepoint', nargs='?', help='Statepoint file') - args = parser.parse_args() - - # Hide root window - root = tk.Tk() - root.withdraw() - - # If no filename given as command-line argument, open file dialog - if args.statepoint is None: - filename = filedialog.askopenfilename(title='Select statepoint file', - initialdir='.') - else: - filename = args.statepoint - - if filename: - # Check to make sure file exists - if not os.path.isfile(filename): - messagebox.showerror("File not found", - "Could not find regular file: " + filename) - sys.exit(1) - - app = MeshPlotter(root, filename) - root.deiconify() - root.mainloop() diff --git a/scripts/openmc-track-combine b/scripts/openmc-track-combine deleted file mode 100755 index f69f2151c..000000000 --- a/scripts/openmc-track-combine +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python3 - -"""Combine multiple HDF5 particle track files.""" - -import argparse - -import openmc - - -def main(): - # Parse command-line arguments - parser = argparse.ArgumentParser( - description='Combine particle track files into a single .h5 file.') - parser.add_argument('input', metavar='IN', nargs='+', - help='Input HDF5 particle track filename(s).') - parser.add_argument('-o', '--out', metavar='OUT', default='tracks.h5', - help='Output HDF5 particle track file.') - - args = parser.parse_args() - openmc.Tracks.combine(args.input, args.out) - - -if __name__ == '__main__': - main() diff --git a/scripts/openmc-track-to-vtk b/scripts/openmc-track-to-vtk deleted file mode 100755 index 82439bea7..000000000 --- a/scripts/openmc-track-to-vtk +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env python3 - -"""Convert HDF5 particle track to VTK poly data. - -""" - -import argparse - -import openmc -import vtk - - -def _parse_args(): - # Create argument parser. - parser = argparse.ArgumentParser( - description='Convert particle track file(s) to a .pvtp file.') - parser.add_argument('input', metavar='IN', type=str, - help='Input particle track data filename.') - parser.add_argument('-o', '--out', metavar='OUT', type=str, dest='out', - help='Output VTK poly data filename.') - - # Parse and return commandline arguments. - return parser.parse_args() - - -def main(): - # Parse commandline arguments. - args = _parse_args() - - # Make sure that the output filename ends with '.pvtp'. - if not args.out: - args.out = 'tracks.pvtp' - elif not args.out.endswith('.pvtp'): - args.out += '.pvtp' - - # Write coordinate values to points array. - track_file = openmc.Tracks(args.input) - track_file.write_to_vtk(args.out) - -if __name__ == '__main__': - main() diff --git a/scripts/openmc-update-inputs b/scripts/openmc-update-inputs deleted file mode 100755 index 5ee1f1ca0..000000000 --- a/scripts/openmc-update-inputs +++ /dev/null @@ -1,307 +0,0 @@ -#!/usr/bin/env python3 -"""Update OpenMC's input XML files to the latest format.""" - -import argparse -from itertools import chain -from random import randint -from shutil import move -import xml.etree.ElementTree as ET - -import openmc.data - - -description = "Update OpenMC's input XML files to the latest format." -epilog = """\ -If any of the given files do not match the most up-to-date formatting, then they -will be automatically rewritten. The old out-of-date files will not be deleted; -they will be moved to a new file with '.original' appended to their name. - -Formatting changes that will be made: - -geometry.xml: Lattices containing 'outside' attributes/tags will be replaced - with lattices containing 'outer' attributes, and the appropriate - cells/universes will be added. Any 'surfaces' attributes/elements on a cell - will be renamed 'region'. - -materials.xml: Nuclide names will be changed from ACE aliases (e.g., Am-242m) to - HDF5/GNDS names (e.g., Am242_m1). Thermal scattering table names will be - changed from ACE aliases (e.g., HH2O) to HDF5/GNDS names (e.g., c_H_in_H2O). - -""" - - -def parse_args(): - """Read the input files from the commandline.""" - # Create argument parser. - parser = argparse.ArgumentParser( - description=description, - epilog=epilog, - formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument('input', metavar='IN', type=str, nargs='+', - help='Input XML file(s).') - - # Parse and return commandline arguments. - return parser.parse_args() - - -def get_universe_ids(geometry_root): - """Return a set of universe id numbers.""" - root = geometry_root - out = set() - - # Get the ids of universes defined by cells. - for cell in root.iter('cell'): - # Get universe attributes/elements - if 'universe' in cell.attrib: - uid = cell.attrib['universe'] - out.add(int(uid)) - elif cell.find('universe') is not None: - elem = cell.find('universe') - uid = elem.text - out.add(int(uid)) - else: - # Default to universe 0 - out.add(0) - - # Get the ids of universes defined by lattices. - for lat in root.iter('lattice'): - # Get id attributes. - if 'id' in lat.attrib: - uid = lat.attrib['id'] - out.add(int(uid)) - - # Get id elements. - elif lat.find('id') is not None: - elem = lat.find('id') - uid = elem.text - out.add(int(uid)) - - return out - - -def get_cell_ids(geometry_root): - """Return a set of cell id numbers.""" - root = geometry_root - out = set() - - # Get the ids of universes defined by cells. - for cell in root.iter('cell'): - # Get id attributes. - if 'id' in cell.attrib: - cid = cell.attrib['id'] - out.add(int(cid)) - - # Get id elements. - elif cell.find('id') is not None: - elem = cell.find('id') - cid = elem.text - out.add(int(cid)) - - return out - - -def find_new_id(current_ids, preferred=None): - """Return a new id that is not already present in current_ids.""" - distance_from_preferred = 21 - max_random_attempts = 10000 - - # First, try to find an id near the preferred number. - if preferred is not None: - assert isinstance(preferred, int) - for i in range(1, distance_from_preferred): - if (preferred - i not in current_ids) and (preferred - i > 0): - return preferred - i - if (preferred + i not in current_ids) and (preferred + i > 0): - return preferred + i - - # If that was unsuccessful, attempt to randomly guess a new id number. - for i in range(max_random_attempts): - num = randint(1, 2147483647) - if num not in current_inds: - return num - - # Raise an error if an id was not found. - raise RuntimeError('Could not find a unique id number for a new universe.') - - -def get_lat_id(lattice_element): - """Return the id integer of the lattice_element.""" - assert isinstance(lattice_element, ET.Element) - if 'id' in lattice_element.attrib: - return int(lattice_element.attrib['id'].strip()) - elif any([child.tag == 'id' for child in lattice_element]): - elem = lattice_element.find('id') - return int(elem.text.strip()) - else: - raise RuntimeError('Could not find the id for a lattice.') - - -def pop_lat_outside(lattice_element): - """Return lattice's outside material and remove from attributes/elements.""" - assert isinstance(lattice_element, ET.Element) - - # Check attributes. - if 'outside' in lattice_element.attrib: - material = lattice_element.attrib['outside'].strip() - del lattice_element.attrib['outside'] - - # Check subelements. - elif any([child.tag == 'outside' for child in lattice_element]): - elem = lattice_element.find('outside') - material = elem.text.strip() - lattice_element.remove(elem) - - # No 'outside' specified. This means the outside is a void. - else: - material = 'void' - - return material - - -def update_geometry(geometry_root): - """Update the given XML geometry tree. Return True if changes were made.""" - root = geometry_root - was_updated = False - - # Get a set of already-used universe and cell ids. - uids = get_universe_ids(root) - cids = get_cell_ids(root) - taken_ids = uids.union(cids) - - # Replace 'outside' with 'outer' in lattices. - for lat in chain(root.iter('lattice'), root.iter('hex_lattice')): - # Get the lattice's id. - lat_id = get_lat_id(lat) - - # Ignore lattices that have 'outer' specified. - if any([child.tag == 'outer' for child in lat]): continue - if 'outer' in lat.attrib: continue - - # Pop the 'outside' material. - material = pop_lat_outside(lat) - - # Get an id number for a new outer universe. Ideally, the id should - # be close to the lattice's id. - new_uid = find_new_id(taken_ids, preferred=lat_id) - assert new_uid not in taken_ids - - # Add the new universe filled with the old 'outside' material to the - # geometry. - new_cell = ET.Element('cell') - new_cell.attrib['id'] = str(new_uid) - new_cell.attrib['universe'] = str(new_uid) - new_cell.attrib['material'] = material - root.append(new_cell) - taken_ids.add(new_uid) - - # Add the new universe to the lattice's 'outer' attribute. - lat.attrib['outer'] = str(new_uid) - - was_updated = True - - for surface in root.findall('surface'): - for attribute in ['type', 'coeffs', 'boundary']: - if surface.find(attribute) is not None: - value = surface.find(attribute).text - surface.attrib[attribute] = value - - child_element = surface.find(attribute) - surface.remove(child_element) - was_updated = True - - # Remove 'type' from lattice definitions. - for lat in root.iter('lattice'): - elem = lat.find('type') - if elem is not None: - lat.remove(elem) - was_updated = True - if 'type' in lat.attrib: - del lat.attrib['type'] - was_updated = True - - # Change 'width' to 'pitch' in lattice definitions. - for lat in root.iter('lattice'): - elem = lat.find('width') - if elem is not None: - elem.tag = 'pitch' - was_updated = True - if 'width' in lat.attrib: - lat.attrib['pitch'] = lat.attrib['width'] - del lat.attrib['width'] - was_updated = True - - # Change 'surfaces' to 'region' in cell definitions - for cell in root.iter('cell'): - elem = cell.find('surfaces') - if elem is not None: - elem.tag = 'region' - was_updated = True - if 'surfaces' in cell.attrib: - cell.attrib['region'] = cell.attrib['surfaces'] - del cell.attrib['surfaces'] - was_updated = True - - return was_updated - -def update_materials(root): - """Update the given XML materials tree. Return True if changes were made.""" - was_updated = False - - for material in root.findall('material'): - for nuclide in material.findall('nuclide'): - if 'name' in nuclide.attrib: - nucname = nuclide.attrib['name'].replace('-', '') - # If a nuclide name is in the ZAID notation (e.g., a number), - # convert it to the proper nuclide name. - if nucname.strip().isnumeric(): - nucname = openmc.data.ace.get_metadata(int(nucname))[0] - nucname = nucname.replace('Nat', '0') - if nucname.endswith('m'): - nucname = nucname[:-1] + '_m1' - nuclide.set('name', nucname) - was_updated = True - - elif nuclide.find('name') is not None: - name_elem = nuclide.find('name') - nucname = name_elem.text - nucname = nucname.replace('-', '') - nucname = nucname.replace('Nat', '0') - if nucname.endswith('m'): - nucname = nucname[:-1] + '_m1' - name_elem.text = nucname - was_updated = True - - for sab in material.findall('sab'): - if 'name' in sab.attrib: - sabname = sab.attrib['name'] - sab.set('name', openmc.data.get_thermal_name(sabname)) - was_updated = True - - elif sab.find('name') is not None: - name_elem = sab.find('name') - sabname = name_elem.text - name_elem.text = openmc.data.get_thermal_name(sabname) - was_updated = True - - return was_updated - - -if __name__ == '__main__': - args = parse_args() - for fname in args.input: - # Parse the XML data. - tree = ET.parse(fname) - root = tree.getroot() - was_updated = False - - if root.tag == 'geometry': - was_updated = update_geometry(root) - elif root.tag == 'materials': - was_updated = update_materials(root) - - if was_updated: - # Move the original geometry file to preserve it. - move(fname, fname + '.original') - - # Write a new geometry file. - tree.write(fname, xml_declaration=True) \ No newline at end of file diff --git a/scripts/openmc-update-mgxs b/scripts/openmc-update-mgxs deleted file mode 100755 index aac6959b7..000000000 --- a/scripts/openmc-update-mgxs +++ /dev/null @@ -1,212 +0,0 @@ -#!/usr/bin/env python3 -"""Update OpenMC's deprecated multi-group cross section XML files to the latest -HDF5-based format. - -""" - -import os -import warnings -import xml.etree.ElementTree as ET - -import argparse -import numpy as np - -import openmc.mgxs_library - - -def parse_args(): - """Read the input files from the commandline.""" - # Create argument parser - parser = argparse.ArgumentParser(description=__doc__, - formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument('-i', '--input', type=argparse.FileType('r'), - help='input XML file') - parser.add_argument('-o', '--output', nargs='?', default='', - help='output file, in HDF5 format') - args = vars(parser.parse_args()) - - if args['output'] == '': - filename = args['input'].name - extension = os.path.splitext(filename) - if extension == '.xml': - filename = filename[:filename.rfind('.')] + '.h5' - args['output'] = filename - - # Parse and return commandline arguments. - return args - - -def get_data(element, entry): - value = element.find(entry) - if value is not None: - value = value.text.strip() - elif entry in element.attrib: - value = element.attrib[entry].strip() - else: - value = None - - return value - - -def main(): - args = parse_args() - - # Parse the XML data. - tree = ET.parse(args['input']) - root = tree.getroot() - - # Get old metadata - group_structure = tree.find('group_structure').text.strip() - group_structure = np.array(group_structure.split(), dtype=float) - # Convert from MeV to eV - group_structure *= 1.e6 - energy_groups = openmc.mgxs.EnergyGroups(group_structure) - - inverse_velocity = tree.find('inverse-velocity') - if inverse_velocity is not None: - inverse_velocity = inverse_velocity.text.split() - inverse_velocity = np.array(inverse_velocity, dtype=float) - else: - inverse_velocity = None - - xsd = [] - names = [] - - # Now move on to the cross section data itself - for xsdata_elem in root.iter('xsdata'): - name = get_data(xsdata_elem, 'name') - - temperature = get_data(xsdata_elem, 'kT') - if temperature is not None: - temperature = float(temperature) / openmc.data.K_BOLTZMANN * 1.E6 - else: - temperature = 294. - temperatures = [temperature] - - awr = get_data(xsdata_elem, 'awr') - if awr is not None: - awr = float(awr) - - representation = get_data(xsdata_elem, 'representation') - if representation is None: - representation = 'isotropic' - if representation == 'angle': - n_azi = int(get_data(xsdata_elem, 'num_azimuthal')) - n_pol = int(get_data(xsdata_elem, 'num_polar')) - - scatter_format = get_data(xsdata_elem, 'scatt_type') - if scatter_format is None: - scatter_format = 'legendre' - - order = int(get_data(xsdata_elem, 'order')) - - tab_leg = get_data(xsdata_elem, 'tabular_legendre') - if tab_leg is not None: - warnings.warn('The tabular_legendre option has moved to the ' - 'settings.xml file and must be added manually') - - # Either add the data to a previously existing xsdata (if it is - # for the same 'name' but a different temperature), or create a - # new one. - try: - # It is in our list, so store that entry - i = names.index(name) - except ValueError: - # It is not in our list, so add it - i = -1 - xsd.append(openmc.XSdata(name, energy_groups, - temperatures=temperatures, - representation=representation)) - if awr is not None: - xsd[-1].atomic_weight_ratio = awr - if representation == 'angle': - xsd[-1].num_azimuthal = n_azi - xsd[-1].num_polar = n_pol - xsd[-1].scatter_format = scatter_format - xsd[-1].order = order - names.append(name) - - if scatter_format == 'legendre': - order_dim = order + 1 - else: - order_dim = order - - if i != -1: - xsd[i].add_temperature(temperature) - - total = get_data(xsdata_elem, 'total') - if total is not None: - total = np.array(total.split(), dtype=float) - total.shape = xsd[i].xs_shapes['[G]'] - xsd[i].set_total(total, temperature) - - if inverse_velocity is not None: - xsd[i].set_inverse_velocity(inverse_velocity, temperature) - - absorption = get_data(xsdata_elem, 'absorption') - absorption = np.array(absorption.split(), dtype=float) - absorption.shape = xsd[i].xs_shapes['[G]'] - xsd[i].set_absorption(absorption, temperature) - - scatter = get_data(xsdata_elem, 'scatter') - scatter = np.array(scatter.split(), dtype=float) - # This is now a flattened-array of something that started with a - # shape of [Order][G][G']; we need to unflatten and then switch the - # ordering - in_shape = (order_dim, energy_groups.num_groups, - energy_groups.num_groups) - if representation == 'angle': - in_shape = (n_pol, n_azi) + in_shape - scatter.shape = in_shape - scatter = np.swapaxes(scatter, 2, 3) - scatter = np.swapaxes(scatter, 3, 4) - else: - scatter.shape = in_shape - scatter = np.swapaxes(scatter, 0, 1) - scatter = np.swapaxes(scatter, 1, 2) - - xsd[i].set_scatter_matrix(scatter, temperature) - - multiplicity = get_data(xsdata_elem, 'multiplicity') - if multiplicity is not None: - multiplicity = np.array(multiplicity.split(), dtype=float) - multiplicity.shape = xsd[i].xs_shapes["[G][G']"] - xsd[i].set_multiplicity_matrix(multiplicity, temperature) - - fission = get_data(xsdata_elem, 'fission') - if fission is not None: - fission = np.array(fission.split(), dtype=float) - fission.shape = xsd[i].xs_shapes['[G]'] - xsd[i].set_fission(fission, temperature) - - kappa_fission = get_data(xsdata_elem, 'kappa_fission') - if kappa_fission is not None: - kappa_fission = np.array(kappa_fission.split(), dtype=float) - kappa_fission.shape = xsd[i].xs_shapes['[G]'] - xsd[i].set_kappa_fission(kappa_fission, temperature) - - chi = get_data(xsdata_elem, 'chi') - if chi is not None: - chi = np.array(chi.split(), dtype=float) - chi.shape = xsd[i].xs_shapes['[G]'] - xsd[i].set_chi(chi, temperature) - else: - chi = None - - nu_fission = get_data(xsdata_elem, 'nu_fission') - if nu_fission is not None: - nu_fission = np.array(nu_fission.split(), dtype=float) - if chi is not None: - nu_fission.shape = xsd[i].xs_shapes['[G]'] - else: - nu_fission.shape = xsd[i].xs_shapes["[G][G']"] - xsd[i].set_nu_fission(nu_fission, temperature) - - # Build library as we go, but first we have enough to initialize it - lib = openmc.MGXSLibrary(energy_groups) - lib.add_xsdatas(xsd) - lib.export_to_hdf5(args['output']) - - -if __name__ == '__main__': - main() diff --git a/scripts/openmc-voxel-to-vtk b/scripts/openmc-voxel-to-vtk deleted file mode 100755 index 3f59ffd42..000000000 --- a/scripts/openmc-voxel-to-vtk +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python3 - -from argparse import ArgumentParser - -import openmc - - -if __name__ == "__main__": - # Process command line arguments - parser = ArgumentParser('Converts a voxel HDF5 file to a VTK file') - parser.add_argument("voxel_file", help="Path to voxel h5 file") - parser.add_argument( - "-o", - "--output", - action="store", - default="plot", - help="Path to output VTK file.", - ) - args = parser.parse_args() - print("Reading and translating data...") - openmc.voxel_to_vtk(args.voxel_file, args.output) - print(f"Written VTK file {args.output}...") diff --git a/tests/regression_tests/track_output/test.py b/tests/regression_tests/track_output/test.py index 62526117d..299e1aa34 100644 --- a/tests/regression_tests/track_output/test.py +++ b/tests/regression_tests/track_output/test.py @@ -1,7 +1,6 @@ import glob import os from pathlib import Path -from subprocess import call import numpy as np import openmc @@ -26,8 +25,8 @@ class TrackTestHarness(TestHarness): # For MPI mode, combine track files if config['mpi']: - call(['../../../scripts/openmc-track-combine', '-o', 'tracks.h5'] + - glob.glob('tracks_p*.h5')) + track_files = list(glob.glob('tracks_p*.h5')) + openmc.Tracks.combine(track_files, 'tracks.h5') # Get string of track file information outstr = '' diff --git a/tests/testing_harness.py b/tests/testing_harness.py index ddae89e02..6de475e6e 100644 --- a/tests/testing_harness.py +++ b/tests/testing_harness.py @@ -1,5 +1,4 @@ from difflib import unified_diff -from subprocess import check_call import filecmp import glob import h5py @@ -487,8 +486,7 @@ class PlotTestHarness(TestHarness): # Check that voxel h5 can be converted to vtk for voxel_h5_filename in self._voxel_convert_checks: - check_call(['../../../scripts/openmc-voxel-to-vtk'] + - glob.glob(voxel_h5_filename)) + openmc.voxel_to_vtk(voxel_h5_filename) def _test_output_created(self): """Make sure *.png has been created."""