From 5111aa2621ec74280ca9b762ccc149cde70c531d Mon Sep 17 00:00:00 2001 From: John Tramm Date: Thu, 18 Apr 2024 17:10:16 -0500 Subject: [PATCH] Random Ray Transport (#2823) Co-authored-by: Gavin Ridley Co-authored-by: Paul Romano --- CMakeLists.txt | 3 + docs/source/_images/2x2_fsrs.jpeg | Bin 0 -> 271045 bytes docs/source/_images/2x2_materials.jpeg | Bin 0 -> 59424 bytes docs/source/io_formats/settings.rst | 26 + docs/source/methods/index.rst | 1 + docs/source/methods/random_ray.rst | 804 ++++++++++++++++++ docs/source/usersguide/data.rst | 2 + docs/source/usersguide/index.rst | 2 + docs/source/usersguide/random_ray.rst | 480 +++++++++++ examples/pincell_random_ray/build_xml.py | 203 +++++ include/openmc/boundary_condition.h | 1 + include/openmc/cell.h | 36 + include/openmc/constants.h | 2 + include/openmc/mgxs.h | 3 +- include/openmc/output.h | 4 +- include/openmc/plot.h | 1 + .../openmc/random_ray/flat_source_domain.h | 141 +++ include/openmc/random_ray/random_ray.h | 55 ++ .../openmc/random_ray/random_ray_simulation.h | 59 ++ include/openmc/settings.h | 6 +- include/openmc/timer.h | 1 + openmc/settings.py | 90 +- src/boundary_condition.cpp | 14 +- src/eigenvalue.cpp | 23 +- src/geometry.cpp | 12 +- src/main.cpp | 11 +- src/mesh.cpp | 2 +- src/output.cpp | 3 +- src/random_ray/flat_source_domain.cpp | 686 +++++++++++++++ src/random_ray/random_ray.cpp | 289 +++++++ src/random_ray/random_ray_simulation.cpp | 397 +++++++++ src/settings.cpp | 42 + src/simulation.cpp | 28 +- src/source.cpp | 52 +- src/tallies/tally.cpp | 7 +- src/timer.cpp | 2 + .../random_ray_basic/__init__.py | 0 .../random_ray_basic/inputs_true.dat | 108 +++ .../random_ray_basic/results_true.dat | 171 ++++ .../regression_tests/random_ray_basic/test.py | 232 +++++ .../random_ray_vacuum/__init__.py | 0 .../random_ray_vacuum/inputs_true.dat | 108 +++ .../random_ray_vacuum/results_true.dat | 171 ++++ .../random_ray_vacuum/test.py | 235 +++++ tests/testing_harness.py | 57 ++ tests/unit_tests/test_settings.py | 11 + 46 files changed, 4512 insertions(+), 69 deletions(-) create mode 100644 docs/source/_images/2x2_fsrs.jpeg create mode 100644 docs/source/_images/2x2_materials.jpeg create mode 100644 docs/source/methods/random_ray.rst create mode 100644 docs/source/usersguide/random_ray.rst create mode 100644 examples/pincell_random_ray/build_xml.py create mode 100644 include/openmc/random_ray/flat_source_domain.h create mode 100644 include/openmc/random_ray/random_ray.h create mode 100644 include/openmc/random_ray/random_ray_simulation.h create mode 100644 src/random_ray/flat_source_domain.cpp create mode 100644 src/random_ray/random_ray.cpp create mode 100644 src/random_ray/random_ray_simulation.cpp create mode 100644 tests/regression_tests/random_ray_basic/__init__.py create mode 100644 tests/regression_tests/random_ray_basic/inputs_true.dat create mode 100644 tests/regression_tests/random_ray_basic/results_true.dat create mode 100644 tests/regression_tests/random_ray_basic/test.py create mode 100644 tests/regression_tests/random_ray_vacuum/__init__.py create mode 100644 tests/regression_tests/random_ray_vacuum/inputs_true.dat create mode 100644 tests/regression_tests/random_ray_vacuum/results_true.dat create mode 100644 tests/regression_tests/random_ray_vacuum/test.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 6922e6b89a1..3f87cbd7ec8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -380,6 +380,9 @@ list(APPEND libopenmc_SOURCES src/progress_bar.cpp src/random_dist.cpp src/random_lcg.cpp + src/random_ray/random_ray_simulation.cpp + src/random_ray/random_ray.cpp + src/random_ray/flat_source_domain.cpp src/reaction.cpp src/reaction_product.cpp src/scattdata.cpp diff --git a/docs/source/_images/2x2_fsrs.jpeg b/docs/source/_images/2x2_fsrs.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..1c8e474d0e8f7b37adeb6e832b7197f6458f071e GIT binary patch literal 271045 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

o)5qG>Rvezi1bqK8 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%0Arnvrsjl~`G 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%0AmZMe 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 Z=w}mN=0uEx=pg>ynj3}uW#8{F{}0?HuQ31s literal 0 HcmV?d00001 diff --git a/docs/source/_images/2x2_materials.jpeg b/docs/source/_images/2x2_materials.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..b76607eca66106f083c2c8fc2feb044f60d90a7a GIT binary patch literal 59424 zcmeFZbyQVb*EoFWknRTQ7NomV8l)wa5=jB+4v~Ip>;t?ajFyzMKZ3NQ+B}gTTN*ATZ!R(B&9N1OyItbzOae zUtN$8SD#RjkPwj2P|(od|G~h)Lc_qpKtsdcfrW#=x_}nK9e9MR&XthASizwnAfVu3 zpkcm~{8t~B4Iorls9dO22ryC*I4T$fD%fQch!7Yg1PB5c8tBIb1q}xd0SN{J3!n)A z_!aVRXc$OX2r%%=Q4j(I7zi8%0tK-3;^GJU|K|Jtp+a%?A>NVhoZ$aP%oQ)vIdl&L zc*dbyCX0rV%IXJ|DMR5?y#K9K5G#bh9(dZ=Nnz*0h;sIbvTN|2b(8z9;rEDpG zoW6!_k0Jc&dj@w^z8vRoVF zFn*J30`0yGB~iYwAKOu!@v!*)DIWH4?+-lK($St1r-*oeY3%S6T3Ckbky>8L@%c4+ z-|-QFtqrF9hqIGOkEpsQ{3!w|KRAE?Mtbwv8KKS#J>NI`wAw|bi-2=p@Gm^X02zFI zuI8!f#o7l`gBRy93H96+9zS^Tz>-eD6gSS*jcnGlhRm~STYL{#uaPjwOQ%bH*w`Y2 z=R1qfiv2O({NMsyd*e+W{b0OT4M(N{VS`idFU)m|K!4Ww9VwZc5s&4RuZR$G&+;!4 zq5`_Kkhb-V(^B5Rrri@(-T?mb>1*`AEjq#7yXJ03{O`q zj3sUL7ZwrJa}LTpxX5MUvi~DscJ0(wH03RY!nabs{bt>FK8Rwc%C|Y%s7h5F3E<-7 zf73L#xV}-ax83TBg8B5P8(dQ$Y3qL7(R-cIX*wKP-*+G7I~dx-_`*ZQ*9c=M^6_iR;+wV zegj`OrQ`<5?~RCg?r!Gz_-{>LL2nIjGH1F$2Ic8?j^rz{KduL&>H3?nS&w=;X6~Z> z!hN&d-~T$rbP1A!Buw}P{@EfoUio%HDRiF=LGTK8n}fn6eJD|@w%cabm4eyb`^o)V z1B-TxYqYFvVB({r$8VADa(2F&d+2EGE(xXd&p8A5!34+@N}eXV@4ad<0J;!@ESDfb zTE4m*gziUC+<8$P!@adF9v~1h43)bV>nA={g8M-4hRZ3p3@-jcmXS@H`Uh6ndChUN z0@q^x2jFkt5OpaBOXW7cag)6HXuTvL&@Ijf){;ks9B%nZeDH7VKRaNDGsmV|`NQS9 zj6UZIe}Q3oiWK{I5^cfvU${8^r2Jb0%qaI{eK3c5thy6`-x7!rIUnG$+VHnO)hG}r z{pr0w#1(zzv*)&pwBWy*K;VM#RaGJ*-GfzPy^Z4zq_1XQ$#LEChh9O@E&k4(UEGIr z2}<#bN&idiKR>}9AE=pYg}(7>mHUn);A(1-Y20B#)_~bP_xLCMcL>!qpDKLR8;eAp z+uV(q|LDa$iBk`s)4V`v<}G4CcVsnWzwPls>hzXI~{8&8E#FK_J$gh6a{UqMj99@Xf$?+1u=dt7yI zx?rB=CmHn>O(_f%F@bL0o_4-0%rYlQKuHMRB;YR?6$RZF!h$X#)3mGp?g?os)eJP$ z>h`T1V9dyC@wp@7y9-vgsLg-z(R#PMz&l*FK*WjD*8&rh&!GjzP%&lZ(fh^DMl7NW&)tF0j2>i5(9TNDm{Lq`J?HyUgj)b;t93Ic#FM4at$h5 zVItUjum9lutqUPK|gU$8iT{~i3XEFek__~4V650zUG2rowTeMPBxf7tv^w{1R??rYNOn(%k>Z@obGmEm zk>{@B`sNERz?rR%cONkZNUXPPj~+?eUl}p`{GD!3Aw)^6ofAgdmi%hpwcI7mEz33R z`=oSx`hxiI^$uHs<2vI=<}I}tzpI`F34-1j%`aTyZM#eCu`}LuPmKAQ{a5~{!c#L=nYWp-saBKMsgI8A2s95(^oMn0Y zW;w3MEHqGeCoOdzBA3_yMFP`P&@)<>*rwH3!;LxSaWfx%->&9+3_NHV0DX&}fj~my zS~*-qm!KsKSKb@N*t@&m6AR6$vf9N_Hxs-j0mn0**Paks-`CF?R?ZkoT58L73e%3jX2hZKQ+oxwr3MEuWRDZ>+aX7DA26&i zlEU|23;6j3v9>#3Zk`|W$}i%to3(2U*tAEvBlXEM(~++cmY!#>fH|PX3#9BU=NxbJI?C+COCKM7U}Mk;_* zg^{buw`>&}^ArA8!*)-8blJ_)vA}Vg`I^Px_x%>I|)o(zCa`M-KmUOA*YUO z#4Tz6S|p6T?ZSaaX!&06zI3)K3;&m+fRWcf)PWry9v_8AmG#aTxyoV_-yysqa*#3| z2N^E?RKw$oyb!+KiV8Y@BMbwUFa+;Y=$ts1N~;`kyh zEmwM|KjquRY^Dk3d_j1L!?)VAfI^t1Wq=BzZlkL=a$lWRfxily=OGrONRdsqmo(0g zvH$HGIS~#9A@Z}Isqi$tRsQm%z4b{-PgzOR7YXd zOwCeZ27cXk-X7FH^nmSV)a;zL?sbsTGfmj$bKzj@E*yHEa-X01u17z&Zgt|L!Exh# z$*FLD_Jif0-^BcNghcL6{5o{`Pw-h_S{yqjz!Tlv6|@(VrrOCqNR1FLZq3IO_)C!d z&U<^v{Z94Ywr@Sf_-_UMjs9O^^KW$jUFUyZp8rnXHTC~T6AROw6f;#byBZW1F1kGz z7AtJMwE9+P_rzsUk?<`+xFxcKi(1O=x{sjS#eZkk|1kN;NlA4&IHMc2&TYCg^1Tby zwQL3(J)X$=$loIl=AJ~V0Z?*#ei(&k0+{38#tc?w! z;))L}q&dZIR-h`^{}7GjLOj*2q?G?b!2mQe}njR;<^YeF6{|)!A&3}oV%g)$t4YFBu+edhYd-&fG5cUVz$0@-LRZTBqA*iQyTYD@TzP zeb(E5VsGx>x_(!xjzPx(Cy(!%C;yZ8LFd5Y^IQXMQ}z0PB5#7+x@1U6F=N@~Jq4(H zy=r+k34`2=5^l}aOZ?>0ag*SGz;2(vW6k~M$EUpt`-1;q0st_^TBpaFr%&x=J38;) z{G8!Wwp&#Z2|UutaazVHc=spEUwtqRxOUAti|2=yI%>!nO*a$$4SJg@u*Rc{*_31J z`WkIi+vLBo{OmybdL=y>uoh77+xfeP{-pR@;})MlDc+Z+Olx{PcC}yMbODDJ&v&$m zbk&m2UK0`|-$e3v*ll?p6=kAE9Xm&uwBhgczj}a0DQ1J)wSCF+$-khtwQkV^(YWcE zKQ|Sn*bd5j2n6W0-`ZbjyUZHS=K833(+;|#=rrC#Kdlw! zSF$PKpgE3j;XdfxF?g?X**zYtxcZd@A>d?>MT zX!m3-lGN=Iz)bVBSY6Cn$5n2p`GL97n?ZL|>Fqjo`@xj!e$f5%n`jL~=EJ~ZeOcc> zaeqQ?SsI81=?UEwv#>epNsm8Se)gUC$9FFxdM|{L>;8jWbEB()$maR2rBn#tx;gLH zyAuokl>J8o9pxZC+Io`x-VOJee~{jK&>-A2x>|9Vash7?@(-440L+Kh*@I0Y!#fnL zw~_n?zd3t?LGcX1J;~-j`*bdM`-8o`<6Kp|&+Pqm42$r+zneN>^Y=!g{ zkDGb<>-eGt1k!AFVb!y5ruaMb#^eT&gub?x9O!2rzL(t?DEW7m>mFpCUzclpZLlu% zjp#psx40cZHKS2_oc%ShF@`{`U;p^VM~z6@=I9R#B$6k1tBEbF{*ZiQ_vTmvNO>{W ze01D%g@Ov~Z(szYn!=o51l9mmxO z9Ado;s{bkUCdkdfbVUjI9J8uTd|*v(GB?c;IcfM0Zis}v1;Z{T^I97?PK7^kw{&k# zci)L2@}Zl&N|gt;9kG)uV6{m8CIPviCo$=H^C9i(CL2BLZ!Zq~jq0DBTNeu;C3Fp) zTYhn!rsC`kKYjg+WZ#-0Y1l?d;Thru66mL z?*|9MN`pDtNuH7Xc&i9Vfs^hfXzc43NNS_CPdp#L|Bto)%Zc>$Xkpa+WN}$^zl}!4 zm+?K@{WOvzHJKR?$*t^95M(>mnv~OYXnS#C-NxS?BI&c_;v;5T+&99eRp3ma3ZInJ zt3d<21o5wi|AG9siT{K2zv$i?6aR&be~|u}KRW2?5 zrdQVKxw}W{MwbtK%PdQZ63cyvRivWXtoRi3|MyMpx0^1&HWAz;D5 zAi<#idQlS$cz+WFr3Vdzj>W_wsDO%wNkYbIbr*${ocTTrh6nKGCM@tmCm0m?C1_W> zL2sw=6Dr3VIQR2}M`%m74g$Rr!|v+iZ;q>ozr;{{AkJfaU@oAk9X;$;`jMeR zuc)8acP6xc<_-xkztU3>smlZCX@@yV>R=NeLAgTxTB+>2g*dFwp1F zT(IymVf57J4X-KDk+IK(h(3~2u#k9}z0Y*;W0r=Oc}-8GH@|K8X0Anc&S!=uMI2p& z!ts#e1HpoJY7hepS8^*?Ycw>o7;a#?&)ej3o75GGJ2EXu*@2<-kiuwh7!$~kE33!C z$B+#2(FC#H`Pr(jg7|pJf^x8#Fgly1XMtf1oYP>oVWj#57Y4V%r~!27 z;a4uFI8ceN8d1V~X0hte&>%sPV1Tfd>+>6~H-vIUFgawf`Ed)YK?bk$DXD-r&T8|j z%Cs7g(6y_zfI+hO)0ES0Vpv&}vB`zSRnyK4GFF;kHohZ3))a|lVRLy{Q4W}{W(n^> zu&6NMt>J;6VY43mNem(D6x#9#@Bspe(86RgV~BUMPle!6U40kEbCaIXM6< zN2t}Qk-V!DM<^HyDk@Q5{3lUCK@m@2gbgm+ikmpRJH6HRuo!>*8( z0s4MO=N~r{ybW*~3?0x8-Mec54*=`%Dwh?B6*-i7YZ&pS_?;M=%KePZH&rc&Ps7I$ zZ4^dvojvC)L7Ba|Bq80@aa$>_fJYkB|tbl=A1*ZCGC&4U!joGwTCd51!3pRh_ z2T$z+|%;B@tHt)rd zo*)Z77&pjx2XJKFS4VO}jGOivmx>!Cds2u6_6-l1EWD@Gu;;&gsyZXQCP zjOqzCAWRv`syAifl{*2tv_Mz=(cYryf2~X_kT_0?;u8*TR-{XeYr%M3_lu9;z zrOdCjN#v2?ES)F|Kbd9z{D(%dZ*QJ0#~LIme|i2M4MQeR_DTe9R%VuUjrN)>;=yt> z<-YAcFg%kwfvPwPh?%@R7J;bcaQxnS61|grV1RO#wtcc)n|?Xo&IMvD93__7fLI|z zr*~oxvii+PbLVjJpJNVYPm%{Z3VI z)@M_H2_jQ6AvSsybD{Qq7_7)eV(pEaW-{I#W{m2@?%y@I=^B-4=hi({>~oFpvq?R7 z08G1sJwnT*Sso>%E-sb0c=lN6<%&j{3|r zmiM0M>)J)oKJwL^iJNKCYU>(v4+x)EQoM9c_%8QeM3bdx2l{qmN&1dL>J!stz*|iM z93dhlo$eMf^?p@ zP1dhd7EB%4eSw*K?f+VXSxg!unG!>};epo*0cNIAmR`!0uVk>wAEi8LbIxmseYY-+ z8K|DmdgX~jGMF;;6l}0Q% zhyx}mJ`OB4qJBMyPI*LQjd53n)aSl&^1F@gh<;$WL$N7BOd_~CtZm2!z4X1UYH|RF z$^uP$u|eS5V`)m3=R%Mb4Mali;9jK=qD*K50M8efaW(n67~#6 z0p?VHDo8%e9dqBKCT^uQ7^^iK*QQqTd~g-?`38{-HlFcW6X{`JxM?skj)g%a8-?Wp z_DXLS%{{d;asZlotML%n6olB**I=kdW1xg)CEBKkWT|c|5rU$XUx6%#9V}!63yW;k zoRq;gpl2fz*~DRe&$J#G(hR?85I7Oc2fdyi;hkhgMKIu<@zN#^aKIS9ooI5{7esv# z_bh_vnA9O5VM>iUupo}6fq1eeVusQa6m+IEhv|{rczq9sCcvUC4OI!^Xa-nf>qji4 z(>Ay)cGKXbUv!{W#!F@EX~X&i^!hwr%v^EDSV%xUDh}@Y@;+>c#mL8UF!v=kS#*Yl zMd{18B5aRUILm=S+hSzU#X7$H!tpq@A&@3nC$kv>BGxJzlGpCpNOm=;mkIVO!1gwq zX0{m>710SUbZ)OvZ6&)+jrX%y7TFL3k?%RnqdjbZl+7i6S56IW3Piyyk#2cUQC$qO z7pcCPrhQgx7C{-sNqiks71bi%=GztNE0VbB>W@l-9v*wJ%o>V9snqt_>0*J^rSqON zfqdZfF`6hw;RIE{)@1XUyn=zAS+9u;CK`&_7uU?+M>EymCY2`l&I6Ja>LezRIBHC8 zI!PA>7hnz{SfDa^_#h&D$5%PX_tZOrka|H0iEwn1cUc3%oIin3c*{PfXgJNIqs$ZC zHy@{gYyXTACzVdH251VB23QZ4yxV(Vj21XiP`+G(tiW5_pDTj!?0>YVfgj+!kNGY+WzAbI~1-H#W&tZO^j&f1h7dmPcFR~_%U6ZX^vqf?cu4zTk! zW786Uln2z9$ht4Sibg*E&f@bWDCXj!05Gr=HsY<+VYf%$+pL$M(O3G%&;R1(zuL7| zPOo<7JluO{*=~Sh;is1%R_#K8&l#J*ZbRvLVDeGjb@U1&bnF_hXj6P%`MqOxApR-_ zyHWG1Bf7B9hcR56_gxfr+swyQB}&pVC}4a+gGpWJ_ozzZzT0%79=sf@=|1v(9)RsL zrgu+7WqWM!%6estbL^DS2-N1Q$$ZBwKLJmq8g(`6>38QbDe)qy-I*qM$-hr7SE>%Q zuU<4+U?8Ad7TDYjz#)X0CE(z%`bv*OQzP+3t-oXf<7dN?%%Rjni}TX+Lt`TZ#*^EI ztgJvEKbP};^%Hy*aww^@raWL@JqCl!1|l2LcwkCSdk+Zo+m9(XZ%d^1-+2hQ0Hhz4Y7KM0XTL0Qo%dT1h6DG7BI(w&d8RE;=cki4Lw?UBo}!;KY3OBobEx2u34*nOgx-KAL@r!@mBt3e*aW|o z`e8)ptFzd()zi`@!ZBKzkmoV^jFCh+0J;X=`0x@&7}mG~t{H+`P`M){%kNn`30ZBCf=M2QLa+A{2=&iXdvLrFe_B%HP^d&n=EVj5@ zCrPD)%o9a&nUA?aNLf4lMv`&6&%k%n1g53-!WSb)Onv(Z2OXtK8{>ipgzO>o74{>X zvASB`LNV~b?nBE*Q<&YW2>rFZ2fxVNoMk_Vl1r+quZ!NFfO2Jy9$8L9VN zvPOx?hyyG}oKMOwmTeO^Jv`LY`6K)bG}|JU+0e6rc8LYZ+^Jkp`LVXTx5Ox$FZNnE%^92nF`?C$kRrnE+~PiE|7;)iF=*mW0L@Wf(1z8rF_y(`=tGsBtuxPy-dG??(99olxaQ0B~dhU*wj3qL@ zq(oH0588mqBp)!otnuhO)(%rwpW*0l-*{LMHRD|&MI$W+0mFWXY!yJd zun?{)fCAI4_!Rq7;wP=RR}>BzRmdSL;zrtTaME!sl@g{LEoW&j)(Rc-@I$CwSjcQg zIU=SuWK!7a{EK7_ zM#=LL`NI0AMs|285WO2o)?aY23qh!&m(K8<1Uc!~&ppqj@-iKj&#ZSr`X~pNf)n4e zQfv`>FyQT~b*TJB&(?y06K}kd^xz?W8~!=eu^_!IjIYAb(h}>}K78~Tm+;6GRs=$! z{ZH+rtzJ$>SaAXG6;H8IADAfB`npRUZbb~_bVS%RSHi2@C$erNu-6PQ+FD#Z`x4kq zImq+g2Z5Fo=Hnm*$NL~ki_~bEO4BG~q*ed*h#@={qYp`dHH!B|mfrna9=i&DD4z>ok zOoGzlg4BdcTpV|mJ%bxZ?*+kQN3s)(I4MUzX{KC#CCxZ|;J=TMsCitDU_D}XH@+?| zb{DSH$iIB@0f9H|c|<|wM;`8~k4z7+;NYaKz=oE{`~AAb1(>u;aj=-Sa?LhV72gnu zgYVb#r3QwG6kaTM49;vHeopIuG@kS~uWV<)xs13aH zj}jva7o>9Cw%V;^4_7MB9!)~64?R{mpTXr0qQyAHb$yVNZK}8lUXrbB^t7U@{DGg^ zC{cKEl73E}ys4l6Ak7J09G-}gI0g%#8JgC`K@z@?dOFlo!C51k*t@>zN3wnhtD?&D+J*hXJ5ZGYhiJqt|YzaAB*BD#pG$6kcywAw3TEYqy7r z3EGIN<;GGe*qHT`sx$CTWW}?kC%Yb6E z+?rk@@p1fKJ2JeTm&ohodL8+f?GF2=6tW(BTL(E63uzg7Z0G!1Tw{2$9^bxhsD-u3 zi|pE$KmJ-$P*Yh|$HOpDX)5dsDQzP-Cc9ibf$gF%l}80r^o6q)g0{ML>n%aEKof%omzy!y>^Y+E>7Igme?vHKTJ2pE$^!kyh~Hh zig4r+u#PGO9-VtEwU6H#OfV5la<>6XcN9s>94{iG4%yzT7y~3Ur_Dm%+f_hqrfRi6 zl@oZKH+Ia8p^;GJgVdzTEbd!3hqOu9&;(jwocQSL~NHD4#yqt}_vlDSe5sZ6<^n+|ur z8MMViOBr=4L9BZD7bK+^_+5NCwZ5h+E=^S5=FhSO+K!Mr<8ol7l(Jo zya`E)LuxqZ0*Ax;hm%qS&ZNxJ5ACSqQhJu@P7|HOo-KEsx1|+t(_*e5mmTqu{H z$zFn_IYX}39t~~r&2#2gg`JW_cvu~BYHt%;N|Tt^T8j*0kO@q--8a&j)vB|4bA&ZX z-l-#`BGo}&3{4fjqpIk8cD=ym(Dp~eRaHp+{k+fFBHkXEmN*P+%E!6BIG}L&XzOID z8P4M=FqD$fQQpv<5&6ZUE&$>uD|762N#5X7s*mK$rpq0^aXlj21LLN9bHi;hFl?VT zXe0&(L^OonHZ8!E`Xr(8FT^nZ~SYUmeZEBiV#)18^W60be` zy;TV&3vrhH_+Lrs)K<2_J|X`VUm?$y)ACc2>ND0s%cFedNr?=iW=mdjxHO`Mo&e${ z5e>qMXWVh*Mn0kNuFrnx9A;C7ZZk=sAvu(a7cDcwN`SubEw1Wn!hJ>5zp@E4ZoMwK zD`K4C)bMaZlHX87PAw@Y0a^B`W|e313#}i19Kp6%*A-)wf!Niv{mqq?Axf81eSpf^ z6Lv@O03y_|yvOIQjGveddPMtU3%O33?V2iK4Ss53vX^#J)lKgA3zFb}x-JSDBB`% z^Y&J+y-JW(PwvcTj<9yMMNS_7)kSk_oKtpw9O`fQHV%tNlT*pF_d4}M5Q#?j6yPpF z`1415L&qDIh)xg4-=0Za=lWL$N7K&(7zuhOpSlXXaSpwkoHV5_q8-P_zMQP|1jY3! zs+-B)0DK$YS-VO)H4Ufe`*r;Ud!)7vPB}tp9CtetIvNQGj_1N7_^S)|jD)JE#yRt^ zBM#HsK0mL2BrHXW)jL<(qD4buhJFgwX9km6pJ=ocF_H>#uR%SjscuDnpKyF4cnNtV zOu*CJP0JGM@z$q_WCP^x?N-WA*)BN2^o#xZNFB-@oPbi7XTA~@kMVss>8{c_AOD={q~9GSM$ke zLuu6@q;Z^CT_9$;n<1#dXbbb<67+;8Q5unsWJb++rK7<3M{b`R-n2V^zjk2TUTelp zRhsntSht{n-MnogJg$tDT$g-4ayuc9ia;ihGhIh;f7B(DV0|)#x9cd5C|0kVFnxh& zbOAYlyP2SOZ!=q=VCqH3*Np0AnMr@``vQC!5^A#(5jw{-(wc#hrc^;cQvZZbB7qLt zgjc?5{B*l%x3Oafa#j5hM|6^6<|Qbk>M_kU=^du86fQ*rWSm3C5-&&G6W^4S))QS2 zPM`VCoKcmXPt8hd;*l^=zIK{-;#}dFX?L=$c%qo;G)RFJSSzj@x%Vww#RXcB4TzR#eCx-U^q{v~lVz5s1v<>qu5d z&O?kZ@HYO?*e6CvQE!EnKe*PkzO=V{hrs*rxXf%TgGwcCpye+6==k&D1e$$W ziTZ_Hp}E4(Yvl;bl}~ZS`%Z_3GGtEt>(SJUj)PY}Cv|Q3KTcKTSgsmzbbizyy6LH~ zm~dU;**wz#r+@_WZtXI-|3vbPs&_M0!SoY+DANofwyYtzU*DQ{RyWUG;prKfM{ZA_ zJwh!#LEMwRhyPMS=Y>P_1c5in@O`(H)lF3FVXe@SF#h04b3TnDw<4!SUR&4Sfd7EqHFx*C*6FzQIzha3 zaD4IH9Ir@G+7J95uHbt5LBm3%6t-b$eETF5@j@h}l`xt4=36{pv-*^ZsinyD6b@;Q zcX-9*(3sLViMV!D(EECu?-f_J@I#e+X=jq2aB?J2b*O21%4If9sht%c<0@FDpIW3U zXi*9!EsIP~t4$`J#kU;aH*2e6`d|hRLtV?Y9Hfa4XV}1328*}72@FauB=#X9|Wy1 zM%y&(5%Yz{G}lHxa}!(+OClcmB>`y%i<0Lq#!GHd{jHTsd$Xu@l3nD1a0uXUf)%!3 zo4t=1r@0@XAqT(ZI20F`G(*I335r&HKrTn^Pw^5#`N--Lgu0h18_)j2M3YTXDMZPX z_w?H4!C^i=9z6Bj41Kb88RPU7{XQqv6U;?~*bzK?vO9YA@Ay3)Tu{n|^t=0sx7nsI zWgLmdX@J|8UV=WS87Q6?J0*l2_K6rrg&hYFHb^T)n=1Auhf%4YJ?lXER(dWTvX1sd zAmb@LGT(~OMJ#2Ta;9{pa=(XZIh4Q)zCqL9EDU-hawZrDYM(HxBv+E`M*U z$1i$Ar6xUz|NV7p`{%*PCCFa;uQ<2_RWV-g9}_XxE|^tl=jh1FETmd5ANi(>t9>eU zxn?D;`z2}X?nn2dsm{>NaQbK5k@rd@PkdqwvqlpTz)t#BMdM^NhCl1t@dV0;ML5v@uq~e5Ji^9PaH!SEuQ91^kXiZ?bYEyU;ymPibHTqvGEyLpA6pV@TavaQWNN)WD^Z%;VsupdAG`OURStlScr+5e&*pSX&!eL z6?m}gY81YZUY!lN>NK`KPGK>EgOWT_C7~;|%&DGQiYtCR5i26k*) zK^LRylAFyj=x_oLou4j9>P^#X_{Ll{x?APG>6yPtTUDi^39B^hPJJ!QM=n|(q(@9Y zPBY}X3y_2Ro4uqXb3xK(!z-hNBAt>@rRy`&u04L^_d#HSt3}jWK97d0YLaQF4ka_& z?PS!B>mJw(F#9?xANyz4lsx#6fjb$oPH|iwlw?~(y0FFhysz%JikG30r^#BO>s1jj z&i#Ia7A>HRma(kq$ko{*YdVxe`Cyne=g0mbJQEt`KUi5s8AaEqF-XB~)DbyqGaaj| zu|h|~KZLAPEaP zCeVF!74syJ3x|@;Q#dy9DCwK@Q|KEaxhoj`+!UKTFvPCXCyAEy+{*>UvI_<9b7jNMs(#O9wtY4&I&cw)ZYhC-!tT zMis2Cm9As@G$|k#_G2z0@URbZ=MAFZl|nR5+`I75UI;hoSaKL9K=s?d2PzfB6R{t6 z$m)p%={y{+3M(jKmB+h;qgXbL7agIzJYa(GtmYi8p8ZHaZq}ZB#D*(e?+k>)mRPM@ zOEJ%0s&9$qMYtmoC|`spbS>{gb9nrR2h2XNdFH#~G+1Eez?_9g9*u4yG?zbl?%=)7 z>V0jGg&EJgMH}uCzC!1M6O*TRd0a$+I~9wE<0&iY*Eg@H_5xz#oAxJl!lkV1#tpI= zMVFvFi3;Ukcy>XRRUQdJEOHf9Vz^Lho-0SN}*ce`MU@7y+y|;(Hl9EA_YEkQ6 zTG#*lr+!1$=?tx`FA`3Yy#rktP;7~zGilX*KV@4(Tf(0AOp1Bw2`7iKP@cqRrxlp%WqxVsuvaUaem^7fb7bO)glF#u z33ud@x28C_9-+#!Cch@OSrMgydZpf2XwM-wsX9^Z`M^sUMiGMt;9|U^Z0XleSIx1OyqFi-m9fv z%l;q98>=NO1;xvSw1**hD}BIr!rQ9Xc9WG%aX<1o?l<%*xJei4U$myJ2vfm#r}q#S z+>|%`pNFUCafm>BCKkFuO!P<8rujYVtD>@LG05H>ll5HbOfe-+L;53F2f| zO#WUbN;McmK9LqWmYh!;(p8IspbY=vroC_CJBdhu0!)gkw$Q#E9m6iDvG-upk#?I) z=nMCGxUs}19@pqi$EO4}QaNVTAA%`=6yl4#t16T3(__T12i_gYKb|A@c8;ywGZD{%8G;8yJR#r?@VZx@5QYkL!}M=|vqyM2 zvZfRL!-|g|c}OFk6|{56bYl?UXLFyfL{7eC`qT!Uh$ z6Z^%ZJGxI<%{Pb1U8Ab58ZQc@ z+~6zf2g*u_4+=-=-1LpU&rPt{9*;5wpNsSGC0o%dlueYb14+fPo_Al`TAs6dh653? zk+H$ba>G%Dwc|S6d$?+A8pr&)JE#@f5z%}!6wiHO16UAYOmx&7L@z<~DazdzEnM{R z+BwDfQajZS=-s?El^;v0UYMZJkt1`7t;a*yKrwoJP_uFFN#=Qim!#~)B7H{=kuXwc zi&Neeuk^=J%bcu#ZZm!T zuI?BmyLj9)s}D4zQBDx#@>03g$Wl8*29j^lpBe0q3Cv0EhcB6r82fGz?j1{|pTwE_ z9;Q@KAH(sEaGMtqGj2GepASl{b~qBgb;#23aB92wT#~Z)O%vK69a&jwC!%9)U`+>g z=80KuxO~Xl>s9;tc2EC6=FL7t8_zV9;CV$2%aq2ONUSwwCVG{vzK+vC*t6)(y_asjv2 za*ic&KP{h)wkfQg#bq37l?vJB+&)WQsw(xI$T*XSE~p`9L}6<$&Akbx!R-!4NVxnv zyzZjKm`L>Au(?N=ED}+!A5+tcqHKIGL1C#zIHQ)lbh5Zz)(7Hs&vYeW8iFz^+WGaO z?1>>HESn&0{D@~=kn;#Bm+>chObZ1@ms~eb?wdDPvdau&aOF>9<{=CeD`qNgntFbm zdRi>-Wow`|R3HFp+69_?FRn~Yyk!27JE;N>avok+(Lu(3_A*3&;G49-+U-16)X$&U z#_j;`a*B2q4PJsKv+pO&t#9Shr6a>HLrXbm3p+v^VS@p$VWxboHaj@^gG^lQz zft?J^!qs_MN-=lSVk=ZGaD+)iUMTzZ@gn(_l8&IsTbO~$*CWyB=oP-}4_~Swe=YHA zGAyi6KiXiN#g+@z6s2nY;BT<(5f(JTAGf@Z;^rzqn4%^%L10AP#Cyh`9wfeex}47M zsy8s8)Zfa@yes&eMLIU1eH;c^fs@GkBq`{eO7FiBjqK?h#wszSY!s_KpwuT32Jvl zvUCB}Jr98&kE>v1FNH$9q@FNwQhU@{{0crZ7NEv_a;};j5ZQAv4T}p zgbU&m4;CctO%)RaSN?zzs7;)w=jCvVj8#MG(ixx<+fn3NN}|C ze3CpuV}|K-+Bn5LyPlH->LRO;*n}Zc?NHPOa|`kmF_^o%yUBecILotQt(JO(Whnp7ea!w3pCdKdY+GYx22h`~{ zyHAii`Hz}$K0MxTW6+4}w+J454P_J| z9-EugWALU`S3$GP< zJlK5-FpI=gBI$!^LKqVsx7)^%4z#&*X;18)*tR6{6 z2iX^sSikQ`xm|4|54uXORDj!Cms_9v+fUlcwea`O!3}w)lMlgYTr4S>cRPOxsTj;b zlc4U})p&!8)vLOKOI5iE9jSh5a>{7dV?XI)SQwb{UdayKGrdJD0SbmXVoJ^T_ln>t zgN9#jJ2GKA15{kQ?2hMSEFS6z@rsDtP}#cKJ9r~ZPXmkI7swz&89r^mVYx_q_&f8n z^v~;rWWl}6U*B(qK)rr@p1_u7{>}kxpU1Iza@eDkiw*cuKVd7nS2Z6_xmT87y?zXNLuA@gS(Rx#Y>cdK&_skt&8A z;njR3Pxm_2Ij+XMVJWk)Etaa0*0m9j@d-@_p;qIm4s120kvMwqGEQ4#b;YP5l9_L2x}$b2*q?Gf(jKei^c7lzGjbf zNe!(h0`%J0=mV`2w&hQM_xLiiws?E7xMsa^)*ulzxB!L;ZMBcBSYTnvhX_K+i}EkG z2R?SccD8F7HR3yPU7721mjiolXMXa{525x6UKX;oA(E{~6;InK)!*fQh)+(6<8oFN znI)^X4n^IsM={Y-uR2kuJj89{KVAOxio=NJai>aTpx>e(Yph-i(uJ@@ubmejjgnf*yN>v$e;OSzV_qQf)UuSG;%^I0_wQ_&h3#G2zQ| zu}6yA%lNrESS^gR?-6;B$U?UQLqmecbyPkTW{LPeK%o$uVwZ(!kiBrT)G-60(c+u_ zzK2!WBj~(|mK8JQXr_cEQ>UA3IYDlB;g&#*q-a=w2Pf8g3M?p%s8ve6|>!Y|wRgkHd1t z1{yc%0m0cOj=a?h!C7Votzo z6+z9c6QS=^1*YVMc{Vht?+f(kP8%yDQBJyRiI5-TdY}=a^zW|m_=(Rg3}^JGPxQEC zHoy13zEXU|3KHy^3%jvYHGiv{CK|Dk#>s0FeZ_N0m=Z==B6c!MLvrHW6ZacnYeE(F znWdBzvxh4_??+OF^NSQ-i?J|?K;P#AQcPH%3EfYW5apNf{MyqghcAZ`4xj92witw8 zuWNbEk0AeMoYquax7^o^xt{u6uR~!&^GUa@g<(fk)g3=NN5hij;X7I_L08bY9_XesQ@4%6k zBTU>6a;}^MH#*-5<(FCK?zuJaTd&@XbKQ=$C63KVm$zH_ltZvf-t@UJw}>vMEiH|F z3H@bU6QAtvC6hR9gSA4+t1nyKUu3~Q3tyXzQy)5X$8~ZI72C@%@r24n?${f|*3;9@ zPdsrOyTry0WGe`?c(89f2V&wyk)&NOxlpjVo#OFn{kS-~$czA`NM5DiL$>qAD*}8_ zr`g6?|7kV&TIf}Z)N*oMp53FfkkK;o6o&eHM9gMY>T_v}pQ;d25nb^qUI}$X_hTG< zNJ`1X-N=tDj~rHd8VBcJkoxfYTroEpU#MmC4ZzTDENw~xZ>~JNH8=Sr+E{{I1yJUU zci+S}0J4vnP70k8i0&MDn8%vAjmXGE$X;-Wut~5PTwUNUQYd7ZyG>`_4+vUjnBE4R9S2eBB#^+b;2mhD^?io*Y&0ILI zg9pmEw-h&DO_jd!RL9igjhcD7iIrjq;Um_cS&}$>z7PU+==kR#Cyu^sq;pMKrrBG&Qi3wq@_b zyO+;0ys(fFs^sk)(E$&=wC8V5Rry?ha+h#0Gtd=-9x0zVVw%5wbbyjVE zT~vwwdeiDtX+#qQ9EdW5oBdLW+OXtG^n}h0@{d>0%y*9o>#XKt?@&%5m74x^&00Ja zXv3^th$3UA7$&8&=j8GLg9Vnl`$Uf8B=C6hEQ(A(;d&R?3wN_xQ?7^YupeP+7B0~9 z=a;j~IS!vIyFT==I@=B${KTN^e?4TauX-D_>LL@-z15jzbPNugWM_m}hh#P#BmKNv zjj*q`dPbRj${+u^Pg8~KqYLJ?*scAb9wMG4x|~tRr_MjEQsdrFP#pW;y6C9h`$UQg z_qZXO#eih_?gjy-7uHWDDpl~!x>UEnxO<1qL?3x=M)D44zpe{;*5dVxU3*p?B5r13 ztvj!!6G+xz`dI5Z>B6fD)X5tqt~EVn@M)1Lykk}D<6RS5@rJ6X>a|ig)1S)WzF*IE z=%*&bIJ6k%)%|pLV$@cQ3s>*T4%}-i;FLA(cHT+Bjoynu z1YeYoY!|Lugg+ZF9+3uYTqWxwMQ5d%k=4W8Dc=35xiz>ZEI`DC1sI}-! z{8I`oh|WKm`(FNdu+G_PPt>%e%2?fp>}}aflRn*fFtN>cJ4X4sS!zGP=I0D@VJT)9 ztYmM#1Zdd=aM`Gpd<6DmeX(QSnY=w^_G;pB*CNsNp;Nkp&K4tND$1;E_6<-Dn_!xm z*r9=c$Uc9&Au#eQ&2^LOlBv8?JMp@nOizs8c2e_=Q*YxMWIohO(a7GV+k7eH9Di-5 z=9_W#yQBK(y=Y9q{Z|d(FC`%Jq9}5>AO-ptK9RnwTVU0+_p>_XQV;cN!=r|T)4S9d z=!+G0ZVqgbmtGV%+jjD&4o!CpR@QVxhMp3tT=SMxCmt~=(+R7QWA(?GsS_EY3enFK zj7j<65$+K`JuzF79dyCe?3O_z60B0BGt13i=y-6=72f;5XEhLe)fDA@iuUAVrm^xR z0eX;dH@P1I^~NXyx11L1JkBa1*N(ujFynO`8i%+F>dN-}`MvMUQV6W|2%OtK_V3Id zaghaq1Fnq4VOw}VA@TI5sY1mcg{?QjP_8e0j+%JShb|j}IIC=X1QL#Obd>dYSY}Xy zmlpPHV2^AoI`L^DWKJi?2~b@9g&yC4&E3yPW4&Jciyq5U!U@q}CSx3M>{FO)1osVq zV6Ulu$332%LUO1bKs(6@8~eT``rVf~6;+~*?uzH(dev?gMAgdjq>`vV*%CoiW9J(X z+Ma79V>VSENpE&vdAGCs)H5oQJrezCY6ps{XrKrzN+Na4o%r}|_4p_7hb0-&9*$&) zB(xE+2N9Qp#%|8n*Jr-%z3ttT*YE1(G(0x2qvwdH3V63MXk0xb&qZIW2S1z&-%{b3 zBX5#f@1AQOIAMv^@(6GZ>c^IiMeSCa$X!3?2^^>lzNdivu7tRJouI{IZ}yr`@dKaw zbu1w?1d63S@syqs?sKlsuV>Z}>aBQ6a!K*30DOP>$oIC*xN=lY%OH6GCJsZ9m2m1d zIzCKzL0rXGWn6ZdHy(3$7(#SJng=nWg>8CdBWguXx^L5uH*tIw`3Bf^%5slel$Ga0 z*g2#u{RS{!U?Q6|*=>JEg20GO+EFTWy(4}XrjV5N>JEX0qWgsuvv%74JO-liZxn5} zST=a-GpdK<{+Il}6bI=#yNOlpN21{0m?Xfv2Eo9gAi*NS!ht^k34P-X01J5MCelH1Jres&ccjRcl&>~jP>4RcWY_g#b#M8UfVZQYq5Ikty` zH)*7b!VCA(^ZKxw83B>sZ!v zUf!u;t%_>m83s;j@V39B_P-q`t#*nRqOUn%EHy^foS-KDAWl74ePn@vDCP zq1uK8xX#PE%7LgA;rvK0<93|*k38?zGY+>iOpcVLk5nINO=zw&5-DYzPU1?N%D!5) zGBBsOZ<_{Nm@7fIj+`Y17h!WE8{VQAv6-U6WgD-Mf(o!Bf7T`l6@Re+Y{rz6_Z_0H z9O*3tjF ze(bCx*|d(^Hv25(>nmMu9IEg2U{%3+$usl4`c^0xmKY9`Wy?5M2wY`Z#xa|0(mUJS zMs`Voq**V!$t#z5dOdv_olisny z;HSF4id3Y-awyL+gsMh7+)*TSgvznI+oH9kNYy_!&0+@uWuwP-P`JT;edLyG{uUYO z!p}`o$C?&b%8?`=yElt2vCOAAJKB&kT1U!h2p?i64~~o@GTPEU*+<|L$=(NzH2iS* zK~qA#okq9Or66#HEf$fnw#0mF`FgYSM*D0fGEpls(oC<1Z(UVV6r8)-Gq6iNcehi{ zt95sBf_Lt&bR&iFXhqteuf$yWO4H#BcDCD?omzqh9!^p4w$CrAg#wWg75AdZJ}r{E z%I=6m>hNFs96&C#)}~)^79pCv3Fm*${M8e9zoQ5s#6&cz=}Ih>d(AsNWR&?KgT9qt z+&=hwb0C&BLmG-?P3S|FTItkw>k)nM9fNL)N?xZvX#y09_q8`6wq?2BoK*iX@>Xzc z5&U>wxpK4Pm!$0FddqC1jW+2AT$A>0r!& z_QXWX$d;l{917WIh*yXpB6xU;V({iEU3Q|r>eJ=f!VfWC$bfxhMcOo4>0TXr=PFwh zL)v?=&2^ZaWR`J|CTij1J!#scrLiLn3`K!0oD|dFj6$Y^WP&%@mW`0c3}hlqdjx~r zYcpw#_ApT%Vw^+~Mvi(`WRA2XJXJksVVmijdMKYi6s3KJmuMkClwn=MWk-F$N&g18 zq~%$P0j6js#6mTxN8#cc@Nzrhw2+p>`FsOJ7r~P|W+fN{p2{%|!%~AgML4b-?qjW; zyy^hRe4jX0eTNdlj6Mv_LwNMZOf6^$;UMn5<6*;zgK}$=`!}_<;74CX814rs-8B z3Z%uRk1ub^&*$S-K(&LP@^ZZV2EfVvq=|ftcvXOGf)cxjhFg*U)>RcM#~e51HBqk; z3ePU8^C&{|uXKYkyEV~-^E}a&u+Oe)P#(x9{D4=~xmXk=dR1IlR~^T#fe`n}-hF;3 zCprl=Gjs)ZhGmHJ z#FDE|X6tuZ4jQRz<*;3$9tVCCs?ttgegI_VOdPBB3ECBDq8IRT3=f{dl?eD1i)-%_ zLHl@~qDL^Axi?EqiqGFv1KxQ%_^OYcvr5Pkh>`9|lq}#;u?;1VA_<=KLEvT3ZXdPd zxgC)0J9;U&$stUQ)B|-QaUCIXxSZFj~2ghM0jJ z!%v;kVJ7m*SEco%749XVe_Z8jVu*gPCU-9Zvy03M>fm|=@gl_mNbT4*mzxLrst~#sPW-A`zNOzafDc`6GKM0zTclPkp5CD(ANaw5Z zm*w6yDR_F46wjOEoA3=_;&be@E(FGvtzQT1YwK8O*eK#;28do_l$2Pt4Jg9GIVE0V z3^I&xygNiz5DgCHw_pQPH`<~&Y%!V~U~^#uzwBeKQq)4H4f=Qe277QJPyL}R#^F9eki@Q@Mev7skV!Z{_{PBN zN`V|-f5^m0j3wpB2)D2}j{%Ug|42@fejd?H3Et8zxJB?rFhqeIxfw;E{YLxTsCL5o zh1JI<6H?reM;N=l5-+JzxV;!kA&UZK8aXn$l4<87;kKoHIh4+a?Hp2!s7Lz;vKU*F z3rmdfdg{->o|h+y6dtWZ;3`gK6g}M|%>Ve9B-A$P)w-{mr^JQq**L^I^V$W3afqY# zWeLfq@4vJPrb$S0hp=#bF305P5FK^XD1&(JSALR*^j^wJfNb$NoO9sfI1*Kt`U+wc z_IxD@&cU4kz|T+*8URD6u1vh(QsiW#8;HD{7GYa5Fh3U0B^rM^L;xAreDRT!O6LSx+t;eJgXia#iFLPij>_I&B_7>Xmecw~Oi_YK)^3o-wmA1Vl zb2}n3;w7bo@Whc z8Zr-Us2LqPtIqP@8$Gthl4Guwjc|c@QVdeZvTv3lB<5L2;mV~ZI(`YMLzpH?OqtaH z)=ff(vCUm)6*315BMr5~n;u8*xub~Pp+dD5oPn5n14zTaNJXOeNfh1vh}Qv9W(Xj| zsYBSU!ng5*+*CaztFxS-SM-i zcq)wDxr+WU8)5})w+PlG$pH~O(BxhzBxD;EhOt9`d@jnc1x>zQ-y+k7Z4;?{qYoLA ziSAjM<5`jnJxHjq_befn7_>25XrllFX>=g-+=|rdTVIzMUd&`E-WYKC9%>q}#hisP zn}mVY5cC-6`MPjP?nwh@u+hyS+0}|A3ny(z(DfjLARa$WCPxB2SUXLk3ZhLdivlZ zV+p(oi`7-z>`@_0vxFm!#(+~`C8Tg_b7xj13~e8XmADT=^9ft=O&}IY!7hPUe5N)q z^1>mo=}MO~-^ns1lq*USyjpug$?t19KC}>=D5hkiZ-CG%C85c-QZ%qReX;r8_pS;? z1Q$$xRU!5YnG)xVDFle|N)+fyz$IR28C2}RA`8qb1HZ4(-y3CZ7Z2M;@uN+f>WMA{ zSB+0&pe6IuP%zRCfHXxw{Ht#+Udt9Pq`l65XAyGvoukaqlp`L#d8Hk<4~mNV6a>%} zp!2<8I}VJF-tXvJ$)ZbR(1qKRK=Qs~fRmY?dJcSauQVLoj)Bk`%J@fG0+OX~pdIT( zm|byKVjLZ7S|5UQBFGuKY=RcV=;m^utfWAR4S2C{fJ&#G(m`+uqrw^p!50ljWU1=y zP-n^#6OdvA%msnhL}6)wPle6YBd}HL9FMl~AS=&@U?+}?5=n^PGDsaF&XEeOfgh`o z(@BIVc`-fjtrhqbg>UQn=s}qhxcD()ODgiw`FZN`_3hP2lu5|QA?Vh?-hp%eB#P~p zWa1(VZx89<2y{c4uerFe{`^rP=f18e&@o2#5o=$L9(@ijz*9mbrWOAMWN=8q2Y3pD z=-9T$km^Ilb?~9%RxKTxJ>h+J8#1!@Sq_NV4`N~?Gs=;FKF2~N)@%iquMu@-J(Af5RNXCvKmWbkS4(!kol6kLbcCMs9859j%k61;Rxffo|+k~BoV7KL37fohi! zT$*Q1yDH7+02*nvoN1PAq!r7D?qKsN?%y&cPeH^|MkL}%AQ|_`DwVCag(EM@uatc* z9QtLt9*oYZObo!&_i=%%T%<*a+j*`cN`~2ae%7(7+o`hnCYUa0VUlUyPEkb5kUhp5 z(*e%3)_^Vj^;`|!VeWhH zz~XlEOCx!1eO=F%SgY#tV-MOP%e$Kg@+kw&ZFk+4>BcHeY0p>CJ}WKx zU-kb*=6{{w|El4!3K`lLt!Fg?FGZ!4qD58Dwc&J1UuiHigG3Cz0l>Et*|5MHio?Lc zA%O2Ce&2)~8$iV=u5Ka**|-X_W7Qsq^BC6Rel)1^uMNmWslEYL8_0;IaO!TeoqFqr za`9}R7Cy(rJIH?Gour#8TAEPq_YELQw3gv*1=Cte{w7EW4@0P}U{zDmM1*~Z9k^rA zC|oOS@KWNkVuxrxkDy<+6rLm6O=hqf(ckVlBuBWA76vmUhl+8=9T?d%6j z>}Qlu2sP)mPfR}PWIudS%HVOk*j=aO^Iq$C#w9pTfFm8@s=6F^s$2`v)Ydu3kT%G+ zvAd^J(utDm-_DF~uDFTS6!?aGF6{)NJ+zKaZe3i@gol?Wzu4V@O@}suy=2q~9diNK z>#2awn)HnP`qHsreo6SVhsAk*+{6Ygupa#n#^{bpfjLGTs68~4N;t0^j0J0r#)lsY zj}uUZDJ6Z#)lgV!33$7SZtw)zqm+R>zie7vzD|W{nR8U7OybbKARxO$rG7E|rE;;0 z?o9`;-J6EhoZPp}*LiyG47+zRKDwi$eJi*;bxfyW zEM-WvG3_g_k@H`_RJ_SWNSa0531<^dFaAj^Ll$o3uw(R15sNAUJ4-~J_5(7dVV(8t z&$ni%lunu#OM=*lzEjV31dw`Q5zx723bf-4O-d` zObqyqX`uCa1QIZ9JR>stn&C;r-T6`kcTh_0%<%IHcZAR2b9!)zsWnOypZc9^#-3Zn zC#*gVASy&&c2-dqA<-~*OL>2c$tEkfGKM>_)H3z(bryY0`z_i%_(Udix6}pRB=WRC zYTcx!7~yi}p+1|Hp}w^jR=O&+AuBFM570WuhSQ!L&=qkjC>+KIWLP&)Wxy*8_9O_E zKMWYCa=6TIv0n>BC}SsBbLY+DOWe*-(%HMTS+418EPH5Da{5#7$f z5`1RpdNCKibht5f5&@u%#KdO?RlJ$Vyt@}1M~pU(OwRSNrj!ibCwGFN0r&BJ(IzQ* zLnE&ui+O!v!_7swGOL-Y>`I_8ja6`CcZ#q8wV2ts<)|wk0s#a13)u>M(d0~6Q?eM_ z^}S8E>62~dFG&~s+|7hHcx|62C|34O(3~%73nAy(Z9XFFZdi4}eb2b*AOYSqorE4e zc#zOUPz^?IVQ*r2<}g>8Y3^-<48OZDo`pRb5n0#?++sl^g`$Iv>t}uE2i2F7pXz(? zICeVL;1mg`vIBb*VsR1jXN|di%}ZY?M=|gt?Fz`R?7w6=k$NW^)7I5WRm~;8Dj@$c z%t`;;AuP&Dl^nt3MMTV!=}gs&b``Wl)G5K>?Ps5x-MoNnE;RN1X(awF0*pIf@11Su z+-(VR8or-Y(`;#;-hy{3{l=ki$m4MT^T*8(>|d&@j?0}jdzH}mwEW*%H>~-wwLXnc z&cX>_Ko%fc74Eg1Ws$nH4+xD&8t?Nk0A&_+Zq!gV#Z4cC6452A>p!3 zR-8DP9qbuweyalG&g)HJB`ZX9erZ6vkjlkseky?cCbE3cC#B-`d@FkL$6}FLxZSla zDD@#>W^3dgq~+adW4Yk^tJlm%~TaGn-#q-2w*_GHcpYXGg4_mPf68 zY2mX#1r0l1R=x}Lq}ll_JzPG>{qc)1+|rt^mE0Uf@5+v9SPj~d?0Zm#GDY{h@ZJuQ z)&$yc0xRWQuQlN97uoM(qWjCLWZ zoMcjo`?>T63ZHQVh0q@N2oxhd2u5^Jj9|i@VK5LLKewybvU+*;`Rn14Q|8xqdY;o) zz&qp^wjeqUJ0~??0l(00@zT67us<^_$!&q0A4kaHSzD80uV02h;&D`dU*!qy-hvr& z@;h=mvJzBM(u1@4#K$!H5~`f;ZOyp?v*^`rz?Oe0Bb&XIR=k+|5aTOd7hg|y)Z7GqdcoVUta)ee_k%F(e&>1c-ZN0W$V_LK?20tnY%bu&jVG)u(f7qE*@{-oZOt=jwIk^yPGSKO64r;3DEwNXM`oY}9H!(MLVVK+~twcEj*{ov-g&@?~nJ zXbzu~_#Wa2en5tfN6PjW?O3$)gW3ZaoH7mW^Z{u&I+}s8I1O!cGQ)XOL6ngUWmTV? zxB)s_8!b3;t;>UN0GXLUgFcgk5JeSnDRV&z&yHTM^eRp4qCBID&}R>`mXqI>DsCm& zb;pIJ4&DXVir?o0on6zx#;95%ARh8Or^7mhloRt zQ;*eg0_}+*r7)mh=zK}%IaL}PEMWlBdA%RO)Np-p_i>!ra2Gvt`G&fNWCb)6V50%Ul zC`Z#~CTiG~%c1JeH8r%6BRAlwPz2|cB-|*HZ?qc~jH6r@)p;J7wXFJCs(^e%7gzMp z(d}uP2dY)0zGxR!lxHa?~p06%VVsh+;6BPpcIEu=XG1M2lreTfbG)}a=T_8TB5 z!FuD_MCHr=yvxiT)h`L&Z@j^`wbj2?oJXw?&A+s;wp*pIQw`Z?=u@@$GKO_K=o=tV z>u^N)>Ti?4c<->hnTedeEkDM1Y+oODuB4UZqI7I~Ed6LN=k}Xq$1%MT4`Wv}_0b9S z3t3@>2yMNO@Qx4lFX)AJ*0)q&@)+f@ z-m0L)iN%G>?fUdlXI+T?=*fByns&B)3Z1Rpfs}@XNqp6AM;6EW;yKrYS%luzyx3=G z80u6(vc!HTxaV}P<_JvFhF1Kxc(IKY%u-%)Av4eQ1ibmIuq_D#*djEDN&pQo9%}cJTfV+0q{I`~6xICwn zS$O6T=Sz|{H%3Z7(HE4Tq|;gKk4;rIj~v;wYASCC(u3G)yF2Lu+YpgiMsH%h$Un?P zEDfsf-~mRKV;rPwR;KjI$ePBC%)Q#rL~`P;qOok@dZ^F=i3h4=RC>dj*P6hqx@E@l z+3v<(v%+EadvjDhtq6iALc8zYVQg94w4C;7wr+{?LA1*!(2?y@?4@V|>-?^b;3*~!NVCE0{ZmQm$ z5Y>0+xJUbvUun*JiE28zN`i(Th&Fy}Y=X2cs`De{sHUhHKuEYC>B%C*1i5Q={j=XueQzIBH zl>g+OhKgzR7o0iGqlmJEaXfoel47q_{OYE6jD0Or^GCz`NpYRWB}MJNQZEz>Si|w*%HdV>M!4NnfFi+f2Sbw2<_=Q{6J2ew zCHVOmZt;Uuu~E(73iZ9_K0?=`0HMN16ptFRTMD>p8(K|oFuHwgS(Bt>)45k7m>u&V#H3=LpW4Z^k2Q7CfR}iDr(*Jwpg7xwpQ2u#tF|8M*n! z1zN^5%9aBShQ5#dTnXXk>Sah~Cs_jB&chX$v~r+EXRquK3LukgZbwfR-C68BHe0|qEi)uQpYO@tFeF6`+PL*e-M#oor&=ql43RKA;65YK z*4vgMjSuIB8N{-8Jar}Smm@r`4eoIMtn`MmqEUnw=6?6|(ej?@oUX{Jrz&tPw2iN1g63Sbmw4IagS!_s~GO!#&~h!$r|I!2R4xV}gSq-;=Ug@;gR1=X1Pu z55hlbRKJ+X?|$T4zFD>op6QDF*D^fDZm4e2;TC*mi`jd999L_;hB@-tMP}(s9cj|( z1;%uR(M!+ct^a>dmumk(og_E!zS}Wsq>gdQZ#O?~1z$s>f!_>=fj+teewOEden57e z{+}IKegCuk(A)(7FO&h__ERBPMd*NoHbMZyPuyz>j-COyQE}2Rq-#8&^RIXTv2l_!@`}i{6^)G(|ssGmbOBsRsS~mi*LjU6b4G0?LU%aa`T<6be z0NOt~01e~2!Vf^;|Ct2<=l63V_CF`V-IfWWj} z*Z)q#`TWfU+Wt-dP0>Ng?|@Kp{4MyKf|L9~qx@01;0 zfTISJ-vRk`EdT(u*p)iaM*iprYSf3iSOxWPb0fa96qEihf(m=wFj6VcTzXpc5}x2K=1@0@y{r zPpZzpE(2)tJui?3^lJ_9=)VF4Ja#yKse)+p7aPbS_80ln83WST@2ia5Pm;e9&|0n% zuxf38aj&0qAPMNC3O=hWKvMrWekz#~^baXGNebnC2L#;1CjU~Q75j_J^-sy`qJPpqJOp?jJk?)6fY{elf1-Z?f*k!XHOhZ+e#7_+5T9Sje+kY31du=JA^xrUTM7cmpV|Td{Wj|l z0R#}dAE{puCcohQg9QQP`_TJ`M>!BcVE$A{+Yi;>63~YH zXznW|C{wM4g?T55cuD(516)J^MB$(hYXU~PrPdhnCNSX-;q~6 zOD*;r`Jdqakp&6}04D1P<7a{r^mF>xDF`6HALU|D>3{VP3JCbhh~rm^aL<3m{TJ^q zS6BL%1kCv3So%A|6(Ha=)-T-Y+24A9q^y6in{Y3 zjNc~z0tBL9CIAfGT)ZJ1*I&QU{`j%>ze{w$f*;~z#s)vc2ZTq0 zJi!Nq##caWDgdXrsSlQ#x(oOjzCB6~v38TO#jA~FAs?B<`Uc>OCjAD;T-78fPQ5+j z{cM+9Ib%n3@D!77O0UkU?!@DE_cbT2i?v&4nU6TdWoUPM`sO-tmj1>mOa*0$MYjs=lXU!W z+9jbr+XqR^cx(rAwACnx-NW%ms5F96Us!KTM&A~D-^D3>^BE)f$Iq2;ORktv_44|} zh4CC|{ijA!>F-p7&hq5hY4xSGH(^NJ!>TpT(;e?BRW_NX>c+M~g|{s$l6)XS$p3JTDcG# z5H64t>dZtv%}pqtjVK}-Ej$R!CbnSqf7j2LeYdT!WwSCt?BBmDjs|jYYD_e#kzBW)rN`8UEeMoF==IDMT|z** zeaVm^#CDHSY!w4}&``>_9lUcQ1}-qH4_+J%TYjLSz1@-Yjs1BfL!X+t%tsu&PFpMq zqo-t@{WWt1qjd2ma#}vQNrc+jEC9+2*M43sAJ^oC40CuPS!>F-WWqfR1#)nlgk48s&JXk}IyJUX8QQVV3js^lbdleHbu+C=nQ z%-yAqwHIMdp^YjN&$B?+jMfZ8;3KvMg0QFYU)oJO>tMJ$<1z@YzR{um>5h=D9;bu)*2IBnbvLUD#YwS&cEEO<$nz)djRn>GIzXWc~Uds%)D<&M)ZHhGiuEe&uT~3lr zLPsI}UUv{ysFwa~183?t0Ir=IWb#Zk4p$xwv<@44WtPFT^9{hyy+^xQ-y9TY-K<>b zfcg0A?4;w{u^y!P?2CKQR`889_EwzCwq4#9zj*Tc0R>`3UF+&R)NuQ5csEf;)}sfWcpM#3q?(d$g6oK4Ar+$;n+>P5MtTi?(EDl>b`%x#2j~MUfV1(@#yGUH zvIJFPl=Bug{Qm(zu$5CBKaB zko@f9V`73zIc_zgyhPho4IQpBG?XVoQ0v3hUWh3@lbz(8RYl`sUSJa_5$jeozBQX$ zX@MsIJZeSqy@}04XIYfX;Q>2fXGPX+qy+4kT2}Yq?H9drfTaT^_$9ftRCFxtfwYhc z98x#bvJI?{q3)tdTWP)^W=SfKvlhC=_~$N+&MsQ8_^8Yc>m3VR0GAN^@1tiq5(TN_ zqXuYxJUTg)TK>yYI&C6dV~+pbLY;j(k@=09LD_&r0}u~$KHVi@7h=dBM>Nx`NFx z>IZ*(K7Xf|BcvXs9I?E(6mNV%cyYj36+)a!RLi#j<_q2AC;;plbOw7W0DdLOh(Vqn zjZjX!`Wz`<{#kd{7#m#N=lNXly2>h?9kb!SDmijCR4yemsg@^E8yL{h28WG|{Q~#M z$Znjw1D?Ss8va=Pm9s>Zus|Vg2_Y7REOZDQ-*Q!;qS)}|x`|C9cw{P8%X`LahF2*S zcd!Kh5})=0yAsgoMk{v6qbF<&EM|pYvmY`wyVj}nQgNC@57T0HcyKv7$r}$5K0!4I zBNj&2YbOy5e;|em$}&N`aqLwN9f#Yga)1;$CL{RCLZmx4#~!OcGjvpF_r~$D%3_j8 zdTsZtbWHCJF9&+Z`dxu4M*GjZFMW-i323#jyJ{6`0O``&E~_02dss0<*j#fmJ{o)OmU*NM8zdpW-ZR|xoBrxQS&oxG^T+Lu3J`Jqc&10`}PfFeD5@4SN z0g6k3-42~Oq0(6&Of_}v!p&h_<7x9(;sA@n9P*nI;y zUy49`^6Ln+hD&SceE$u=4Q>BF!rw?$FSJK|Y>I>Rjo5=N1LG>TU#A9osVWQ5kD1=C zz;#DGC)*AmV<)BqZ|npKn??4lO2n8d05ulNDIew7oP*cQT0~VeBH)VxMW3e*t0x4d zl>-n0L`-O>^GW#3dI%(QS(^FD^?V2-_=C>iEq5H;GXO{!-=v>sUliMnzhdZEB(lVKemWzx4623ydkd|@7u#HGMv61Hvk z?S+%LmB*2FhS?>B!&gQCk{AXWxi00`-x-K)QBv^TDpsNd?~4kJ^fe#az?JOiER-k` zJ>|-P+3r6{{;BUqf)Yb{&J#Z4#nlBFZ8g+KIBteAlSoO_vy6V7H zy>6I7SKK&R*i#CeEIAx(PMjgjm|><*EeLhQcqFf(V0_j#qmd`t;FveOc>^39E?1(o zP$h60>S)R%C4IWNL~WCLrFT}62h!FCao@R9l3j>e4&s>Q4#7+Hr@95&%jZr1colrP zD?MP~%O@Ox=f|pJG?ahAttLQa=6Eaqxl-ydwNNj#!ZVmkJtXzFbooT+J$dah&f2%a z@6WSc1s@vEEop-(mn(;u^Ops2%6a54#8IY8sbUC=W;$U&^DGW2 z(dM@-5J@@e4Pm8?-j2MAclhSWBW*DG*t5j@D0g0njW?OOJzcyCI>hzqNoC)Mu@2F( zn`S*uUxb=|59Dktb@;;PtDxW6Jaoa%pX8%&x!kpD@P7*Foc!rU+y_)I7LHlJXW(@? zAs`#PSH=DuyptT%BkROMFvR0Dl!w%EG(*5U-G8?vluMs5PE+E@!i|Bnc*C#k_N`A> zrY|f1?1|o>KFTPuk{eyWfL2_~il&eqOk# zu^UoLID(NMLqg@u-4FD+48B8~W!6xo6@lg~kQ$+!ZlxciFYkm3~ZC9IXCwkWp7uw>55W_Y8i4L--9`IP$nM0UjS|M zv6Nlj<6we5Ldh-vIjPGh7xmLLL$Yyz9;knvbutnJW=V_%6%I za`j2#1%_`}72x29Yradc3|NdNZAGWY4bLF6(8I@%+oPr~4SOlan@vl0c-53?4td2m zf=C*g5VH{;)37l2z90hp1qE-cmzFlv^2f^?ns49(sdTT#A9I!61m7THh29`SfV|`hdCe1iTk7ft5qO(8HSjy0;8#4w zswhn$Z+SX{etdff>#}~5?cy6?;=E5n2l3U13pyV)Cf4LWLH1iWr1g^pgB_${gF75pa1 zv9_wugIx27rSUObvk;e)b@bid67s23wLa0U5|hV-Ueeja4e!jRDQ;1WRdMbzhYnz! zCpCXwvDr_LtW2Z~H1w<7UZ5;eA6myKOIF%{!jqX|bn1eYBFLoze2QYN!2J51{;aj2|-g~z#3R%}E9VleD4HVL4 zEtOetMJ4Q<(G|KEPi&||if0mLD(&t2^-Fj=Yq{cUCKHMqS|tqv6dRw*p-wfzU#_lut?Dl+=RXl zMJtahb)FAE)&`-zaYQwD2xI7wdK1e7Q~xSUu4L#u-c`45o_kW(00Uhx@5`R;103e# zb`1{48yABkRHHe81J88dS2H~IoEFk9F?jD|DAT^chf5Wh%pdxc%jJo2+e<^3vNYNm zgnXNp2W@ZYw_4$l!l?}-kxdEj-XZ3|fbS)=yAac+VGEqeDKtPu!qMIC((ZcE*Yz5^ z2;HXzMU-|`z);yjBqdopx-%Pu^kqE7T7v0i5BK3hzkeNn1Om@ZJ5?^6s1b4^<};!av6p)FO5wF=vr}yClDozU zk`1ZxOWnQ;!RLTt@8IklH2u8xoMaL{3#Nt=?T5xqHiNhv?Sg?1Ijgvk0{SMswB&*I z2MyKF-kK8~1;HKgZML23yJ>&lhDgqYvEHlRtV~_X@6U}R3 zj|z=+K2^`*6@OD6XKkjg%Uit1L}*MPC$S=a3puI>rDD+_4a0$S`}OOhA$_A3G#Un< zfKv;8RsX8Dg0&ghY}Rn_`a8UL`&Q3-5e%5b1C>9KKjP}tW8jT>3B~moB0o7K0X7}4;3NBZ^zSZ~ea_4wKdklV`9E8su zu4}q>o*GKnPP^{?0faAgkfehCD*G5SYV~v0jZmO%R zv$w@gRM0-r9AyGf%0-#pQFoJ43xx~g&ofd8kR=^DzaHs}nnrkpB!4P#YV40ssK&Xi z@L0%Mf3(yfR0#Z8UaXteeVFiQ6k)*aw|!!2XX0v6?laS@>Lku;V}Mt_hhID8#Vf;* zDvNmuAMc67GEXpE;JsghSEiACv1&5ys|`wBuX%av749TJ2;dpJCm|k-k?C5m8jKGJ zp>bd|+8N_|K#t&2eYhxd^n^3!24@OvrNn}L)m~rXsaQ$2`3)oo%C*cMl;AYdEv$2O z0cWawF|Km9fZfCw`^4?I&5uj=@^9f_zaV+7O?K02vq^o@9sg|AVLGCM*YW@+hm?mT zhKglhF3;+X`$Jq%w`aarhR}XiE=;91n-{U&0^KCY((o=!35btwU21hcrReU#XK{_m zz$}~%-t>V!f-<)c(JoqHsUP6xeMct&eMll4*t8Bu#rX&ih8{$JY{P3qLN>g!-zkYz zFbuD7%zAU=v!^9>tjJ-c9{8?nn;upahY7h%X=Cqeg`1@s>7DzW@)3C*rlPo1OP_ix1cP@}kn<0gY&wY50T(9flc`PQ(e-r(AEHxZSv^dN3PRZfX5L<$YC9T+P4j z;4s+0FhFp34?zM6Ho@H?Kn4vEAXxCA6JP=i?he7-0wfR^+=E+4aDoJP&7JT2pL^@P z-M8~{s&>`h4=umFYghMgb+2BlugB7p>X(7S)>n_BJ`WF`wvE=fPAJqK;giO>l;=51 z06f23x{0dY^|L8w; z#7jkN@~RYw)Uh<;Y-U$1a;l}>LK_&RFZEc~AC|Yz0rJaR>}pL#Ykyp4F3q?@a!XIv zv;_x({&e<4%~j&Ot7e=61vbuXk;L3sphr` z8(KB5$VyXJ*m-3QQ5}9)=DAI#U8_CDzmvUoApj_u6S%^Y?mHHOs_(O~8(iSCCfO%n zDB33}M()068Zi4vQxRTnY;UwM>TyUzBL;Xr&O<{HiGLtA@~wR_5Sg%@;@WmW?w&q! zjm)Y-`8y`~tU3fuI%{Y)>MwXRx86FYt>a)NyJ%qAQZ2l|G3N5n*)n2JYpfvyyVZ=m z(FD>~7o

N1Gkv&N5JUzVL7}n>CVY1IDMtkdfQfL<^Jc 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 literal 0 HcmV?d00001 diff --git a/docs/source/io_formats/settings.rst b/docs/source/io_formats/settings.rst index 9a339fb471d..6318a991601 100644 --- a/docs/source/io_formats/settings.rst +++ b/docs/source/io_formats/settings.rst @@ -413,6 +413,32 @@ or sub-elements and can be set to either "false" or "true". .. note:: This element is not used in the multi-group :ref:`energy_mode`. +------------------------ +```` Element +------------------------ + +The ```` element enables random ray mode and contains a number of +settings relevant to the solver. Tips for selecting these parameters can be +found in the :ref:`random ray user guide `. + + :distance_inactive: + The inactive ray length (dead zone length) in [cm]. + + *Default*: None + + :distance_active: + The active ray length in [cm]. + + *Default*: None + + :source: + Specifies the starting ray distribution, and follows the format for + :ref:`source_element`. It must be uniform in space and angle and cover the + full domain. It does not represent a physical neutron or photon source -- it + is only used to sample integrating ray starting locations and directions. + + *Default*: None + ---------------------------------- ```` Element ---------------------------------- diff --git a/docs/source/methods/index.rst b/docs/source/methods/index.rst index 59892ac273f..08aa7d05341 100644 --- a/docs/source/methods/index.rst +++ b/docs/source/methods/index.rst @@ -20,3 +20,4 @@ Theory and Methodology energy_deposition parallelization cmfd + random_ray \ No newline at end of file diff --git a/docs/source/methods/random_ray.rst b/docs/source/methods/random_ray.rst new file mode 100644 index 00000000000..aa436784766 --- /dev/null +++ b/docs/source/methods/random_ray.rst @@ -0,0 +1,804 @@ +.. _methods_random_ray: + +========== +Random Ray +========== + +.. _methods_random_ray_intro: + +------------------- +What is Random Ray? +------------------- + +`Random ray `_ is a stochastic transport method, closely related to +the deterministic Method of Characteristics (MOC) [Askew-1972]_. Rather than +each ray representing a single neutron as in Monte Carlo, it represents a +characteristic line through the simulation geometry upon which the transport +equation can be written as an ordinary differential equation that can be solved +analytically (although with discretization required in energy, making it a +multigroup method). The behavior of the governing transport equation can be +approximated by solving along many characteristic tracks (rays) through the +system. Unlike particles in Monte Carlo, rays in random ray or MOC are not +affected by the material characteristics of the simulated problem---rays are +selected so as to explore the full simulation problem with a statistically equal +distribution in space and angle. + +.. raw:: html + + + +The above animation is an example of the random ray integration process at work, +showing a series of random rays being sampled and transported through the +geometry. In the following sections, we will discuss how the random ray solver +works. + +---------------------------------------------- +Why is a Random Ray Solver Included in OpenMC? +---------------------------------------------- + +* One area that Monte Carlo struggles with is maintaining numerical efficiency + in regions of low physical particle flux. Random ray, on the other hand, has + approximately even variance throughout the entire global simulation domain, + such that areas with low neutron flux are no less well known that areas of + high neutron flux. Absent weight windows in MC, random ray can be several + orders of magnitude faster than multigroup Monte Carlo in classes of problems + where areas with low physical neutron flux need to be resolved. While MC + uncertainty can be greatly improved with variance reduction techniques, they + add some user complexity, and weight windows can often be expensive to + generate via MC transport alone (e.g., via the `MAGIC method + `_). The random ray solver + may be used in future versions of OpenMC as a fast way to generate weight + windows for subsequent usage by the MC solver in OpenMC. + +* In practical implementation terms, random ray is mechanically very similar to + how Monte Carlo works, in terms of the process of ray tracing on constructive + solid geometry (CSG) and handling stochastic convergence, etc. In the original + 1972 paper by Askew that introduces MOC (which random ray is a variant of), he + stated: + + .. epigraph:: + + "One of the features of the method proposed [MoC] is that ... the + tracking process needed to perform this operation is common to the + proposed method ... and to Monte Carlo methods. Thus a single tracking + routine capable of recognizing a geometric arrangement could be utilized + to service all types of solution, choice being made depending which was + more appropriate to the problem size and required accuracy." + + -- Askew [Askew-1972]_ + + This prediction holds up---the additional requirements needed in OpenMC to + handle random ray transport turned out to be fairly small. + +* It amortizes the code complexity in OpenMC for representing multigroup cross + sections. There is a significant amount of interface code, documentation, and + complexity in allowing OpenMC to generate and use multigroup XS data in its + MGMC mode. Random ray allows the same multigroup data to be used, making full + reuse of these existing capabilities. + +------------------------------- +Random Ray Numerical Derivation +------------------------------- + +In this section, we will derive the numerical basis for the random ray solver +mode in OpenMC. The derivation of random ray is also discussed in several papers +(`1 `_, `2 `_, `3 `_), and some of those +derivations are reproduced here verbatim. Several extensions are also made to +add clarity, particularly on the topic of OpenMC's treatment of cell volumes in +the random ray solver. + +~~~~~~~~~~~~~~~~~~~~~~~~~ +Method of Characteristics +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Boltzmann neutron transport equation is a partial differential equation +(PDE) that describes the angular flux within a system. It is a balance equation, +with the streaming and absorption terms typically appearing on the left hand +side, which are balanced by the scattering source and fission source terms on +the right hand side. + +.. math:: + :label: transport + + \begin{align*} + \mathbf{\Omega} \cdot \mathbf{\nabla} \psi(\mathbf{r},\mathbf{\Omega},E) & + \Sigma_t(\mathbf{r},E) \psi(\mathbf{r},\mathbf{\Omega},E) = \\ + & \int_0^\infty d E^\prime \int_{4\pi} d \Omega^{\prime} \Sigma_s(\mathbf{r},\mathbf{\Omega}^\prime \rightarrow \mathbf{\Omega}, E^\prime \rightarrow E) \psi(\mathbf{r},\mathbf{\Omega}^\prime, E^\prime) \\ + & + \frac{\chi(\mathbf{r}, E)}{4\pi k_{eff}} \int_0^\infty dE^\prime \nu \Sigma_f(\mathbf{r},E^\prime) \int_{4\pi}d \Omega^\prime \psi(\mathbf{r},\mathbf{\Omega}^\prime,E^\prime) + \end{align*} + +In Equation :eq:`transport`, :math:`\psi` is the angular neutron flux. This +parameter represents the total distance traveled by all neutrons in a particular +direction inside of a control volume per second, and is often given in units of +:math:`1/(\text{cm}^{2} \text{s})`. As OpenMC does not support time dependence +in the random ray solver mode, we consider the steady state equation, where the +units of flux become :math:`1/\text{cm}^{2}`. The angular direction unit vector, +:math:`\mathbf{\Omega}`, represents the direction of travel for the neutron. The +spatial position vector, :math:`\mathbf{r}`, represents the location within the +simulation. The neutron energy, :math:`E`, or speed in continuous space, is +often given in units of electron volts. The total macroscopic neutron cross +section is :math:`\Sigma_t`. This value represents the total probability of +interaction between a neutron traveling at a certain speed (i.e., neutron energy +:math:`E`) and a target nucleus (i.e., the material through which the neutron is +traveling) per unit path length, typically given in units of +:math:`1/\text{cm}`. Macroscopic cross section data is a combination of +empirical data and quantum mechanical modeling employed in order to generate an +evaluation represented either in pointwise form or resonance parameters for each +target isotope of interest in a material, as well as the density of the +material, and is provided as input to a simulation. The scattering neutron cross +section, :math:`\Sigma_s`, is similar to the total cross section but only +measures scattering interactions between the neutron and the target nucleus, and +depends on the change in angle and energy the neutron experiences as a result of +the interaction. Several additional reactions like (n,2n) and (n,3n) are +included in the scattering transfer cross section. The fission neutron cross +section, :math:`\Sigma_f`, is also similar to the total cross section but only +measures the fission interaction between a neutron and a target nucleus. The +energy spectrum for neutrons born from fission, :math:`\chi`, represents a known +distribution of outgoing neutron energies based on the material that fissioned, +which is taken as input data to a computation. The average number of neutrons +born per fission is :math:`\nu`. The eigenvalue of the equation, +:math:`k_{eff}`, represents the effective neutron multiplication factor. If the +right hand side of Equation :eq:`transport` is condensed into a single term, +represented by the total neutron source term :math:`Q(\mathbf{r}, \mathbf{\Omega},E)`, +the form given in Equation :eq:`transport_simple` is reached. + +.. math:: + :label: transport_simple + + \overbrace{\mathbf{\Omega} \cdot \mathbf{\nabla} \psi(\mathbf{r},\mathbf{\Omega},E)}^{\text{streaming term}} + \overbrace{\Sigma_t(\mathbf{r},E) \psi(\mathbf{r},\mathbf{\Omega},E)}^{\text{absorption term}} = \overbrace{Q(\mathbf{r}, \mathbf{\Omega},E)}^{\text{total neutron source term}} + +Fundamentally, MOC works by solving Equation :eq:`transport_simple` along a +single characteristic line, thus altering the full spatial and angular scope of +the transport equation into something that holds true only for a particular +linear path (or track) through the reactor. These tracks are linear for neutral +particles that are not subject to field effects. With our transport equation in +hand, we will now derive the solution along a track. To accomplish this, we +parameterize :math:`\mathbf{r}` with respect to some reference location +:math:`\mathbf{r}_0` such that :math:`\mathbf{r} = \mathbf{r}_0 + s\mathbf{\Omega}`. In this +manner, Equation :eq:`transport_simple` can be rewritten for a specific segment +length :math:`s` at a specific angle :math:`\mathbf{\Omega}` through a constant +cross section region of the reactor geometry as in Equation :eq:`char_long`. + +.. math:: + :label: char_long + + \mathbf{\Omega} \cdot \mathbf{\nabla} \psi(\mathbf{r}_0 + s\mathbf{\Omega},\mathbf{\Omega},E) + \Sigma_t(\mathbf{r}_0 + s\mathbf{\Omega},E) \psi(\mathbf{r}_0 + s\mathbf{\Omega},\mathbf{\Omega},E) = Q(\mathbf{r}_0 + s\mathbf{\Omega}, \mathbf{\Omega},E) + +As this equation holds along a one dimensional path, we can assume the +dependence of :math:`s` on :math:`\mathbf{r}_0` and :math:`\mathbf{\Omega}` such that +:math:`\mathbf{r}_0 + s\mathbf{\Omega}` simplifies to :math:`s`. When the differential +operator is also applied to the angular flux :math:`\psi`, we arrive at the +characteristic form of the Boltzmann Neutron Transport Equation given in +Equation :eq:`char`. + +.. math:: + :label: char + + \frac{d}{ds} \psi(s,\mathbf{\Omega},E) + \Sigma_t(s,E) \psi(s,\mathbf{\Omega},E) = Q(s, \mathbf{\Omega},E) + +An analytical solution to this characteristic equation can be achieved with the +use of an integrating factor: + +.. math:: + :label: int_factor + + e^{ \int_0^s ds' \Sigma_t (s', E)} + +to arrive at the final form of the characteristic equation shown in Equation +:eq:`full_char`. + +.. math:: + :label: full_char + + \psi(s,\mathbf{\Omega},E) = \psi(\mathbf{r}_0,\mathbf{\Omega},E) e^{-\int_0^s ds^\prime \Sigma_t(s^\prime,E)} + \int_0^s ds^{\prime\prime} Q(s^{\prime\prime},\mathbf{\Omega}, E) e^{-\int_{s^{\prime\prime}}^s ds^\prime \Sigma_t(s^\prime,E)} + +With this characteristic form of the transport equation, we now have an +analytical solution along a linear path through any constant cross section +region of a system. While the solution only holds along a linear track, no +discretizations have yet been made. + +Similar to many other solution approaches to the Boltzmann neutron transport +equation, the MOC approach also uses a "multigroup" approximation in order to +discretize the continuous energy spectrum of neutrons traveling through the +system into fixed set of energy groups :math:`G`, where each group :math:`g \in +G` has its own specific cross section parameters. This makes the difficult +non-linear continuous energy dependence much more manageable as group wise cross +section data can be precomputed and fed into a simulation as input data. The +computation of multigroup cross section data is not a trivial task and can +introduce errors in the simulation. However, this is an active field of research +common to all multigroup methods, and there are numerous generation methods +available that are capable of reducing the biases introduced by the multigroup +approximation. Commonly used methods include the subgroup self-shielding method +and use of fast (unconverged) Monte Carlo simulations to produce cross section +estimates. It is important to note that Monte Carlo methods are capable of +treating the energy variable of the neutron continuously, meaning that they do +not need to make this approximation and are therefore not subject to any +multigroup errors. + +Following the multigroup discretization, another assumption made is that a large +and complex problem can be broken up into small constant cross section regions, +and that these regions have group dependent, flat, isotropic sources (fission +and scattering), :math:`Q_g`. Anisotropic as well as higher order sources are +also possible with MOC-based methods but are not used yet in OpenMC for +simplicity. With these key assumptions, the multigroup MOC form of the neutron +transport equation can be written as in Equation :eq:`moc_final`. + +.. math:: + :label: moc_final + + \psi_g(s, \mathbf{\Omega}) = \psi_g(\mathbf{r_0}, \mathbf{\Omega}) e^{-\int_0^s ds^\prime \Sigma_{t_g}(s^\prime)} + \int_0^s ds^{\prime\prime} Q_g(s^{\prime\prime},\mathbf{\Omega}) e^{-\int_{s^{\prime\prime}}^s ds^\prime \Sigma_{t_g}(s^\prime)} + +The CSG definition of the system is used to create spatially defined source +regions (each region being denoted as :math:`i`). These neutron source regions +are often approximated as being constant +(flat) in source intensity but can also be defined using a higher order source +(linear, quadratic, etc.) that allows for fewer source regions to be required to +achieve a specified solution fidelity. In OpenMC, the approximation of a +spatially constant isotropic fission and scattering source :math:`Q_{i,g}` in +cell :math:`i` leads +to simple exponential attenuation along an individual characteristic of length +:math:`s` given by Equation :eq:`fsr_attenuation`. + +.. math:: + :label: fsr_attenuation + + \psi_g(s) = \psi_g(0) e^{-\Sigma_{t,i,g} s} + \frac{Q_{i,g}}{\Sigma_{t,i,g}} \left( 1 - e^{-\Sigma_{t,i,g} s} \right) + +For convenience, we can also write this equation in terms of the incoming and +outgoing angular flux (:math:`\psi_g^{in}` and :math:`\psi_g^{out}`), and +consider a specific tracklength for a particular ray :math:`r` crossing cell +:math:`i` as :math:`\ell_r`, as in: + +.. math:: + :label: fsr_attenuation_in_out + + \psi_g^{out} = \psi_g^{in} e^{-\Sigma_{t,i,g} \ell_r} + \frac{Q_{i,g}}{\Sigma_{t,i,g}} \left( 1 - e^{-\Sigma_{t,i,g} \ell_r} \right) . + +We can then define the average angular flux of a single ray passing through the +cell as: + +.. math:: + :label: average + + \overline{\psi}_{r,i,g} = \frac{1}{\ell_r} \int_0^{\ell_r} \psi_{g}(s)ds . + +We can then substitute in Equation :eq:`fsr_attenuation` and solve, resulting +in: + +.. math:: + :label: average_solved + + \overline{\psi}_{r,i,g} = \frac{Q_{i,g}}{\Sigma_{t,i,g}} - \frac{\psi_{r,g}^{out} - \psi_{r,g}^{in}}{\ell_r \Sigma_{t,i,g}} . + +By rearranging Equation :eq:`fsr_attenuation_in_out`, we can then define +:math:`\Delta \psi_{r,g}` as the change in angular flux for ray :math:`r` +passing through region :math:`i` as: + +.. math:: + :label: delta_psi + + \Delta \psi_{r,g} = \psi_{r,g}^{in} - \psi_{r,g}^{out} = \left(\psi_{r,g}^{in} - \frac{Q_{i,g}}{\Sigma_{t,i,g}} \right) \left( 1 - e^{-\Sigma_{t,i,g} \ell_r} \right) . + +Equation :eq:`delta_psi` is a useful expression as it is easily computed with +the known inputs for a ray crossing through the region. + +By substituting :eq:`delta_psi` into :eq:`average_solved`, we can arrive at a +final expression for the average angular flux for a ray crossing a region as: + +.. math:: + :label: average_psi_final + + \overline{\psi}_{r,i,g} = \frac{Q_{i,g}}{\Sigma_{t,i,g}} + \frac{\Delta \psi_{r,g}}{\ell_r \Sigma_{t,i,g}} + +~~~~~~~~~~~ +Random Rays +~~~~~~~~~~~ + +In the previous subsection, the governing characteristic equation along a 1D +line through the system was written, such that an analytical solution for the +ODE can be computed. If enough characteristic tracks (ODEs) are solved, then the +behavior of the governing PDE can be numerically approximated. In traditional +deterministic MOC, the selection of tracks is chosen deterministically, where +azimuthal and polar quadratures are defined along with even track spacing in +three dimensions. This is the point at which random ray diverges from +deterministic MOC numerically. In the random ray method, rays are randomly +sampled from a uniform distribution in space and angle and tracked along a +predefined distance through the geometry before terminating. **Importantly, +different rays are sampled each power iteration, leading to a fully stochastic +convergence process.** This results in a need to utilize both inactive and +active batches as in the Monte Carlo method. + +While Monte Carlo implicitly converges the scattering source fully within each +iteration, random ray (and MOC) solvers are not typically written to fully +converge the scattering source within a single iteration. Rather, both the +fission and scattering sources are updated each power iteration, thus requiring +enough outer iterations to reach a stationary distribution in both the fission +source and scattering source. So, even in a low dominance ratio problem like a +2D pincell, several hundred inactive batches may still be required with random +ray to allow the scattering source to fully develop, as neutrons undergoing +hundreds of scatters may constitute a non-trivial contribution to the fission +source. We note that use of a two-level second iteration scheme is sometimes +used by some MOC or random ray solvers so as to fully converge the scattering +source with many inner iterations before updating the fission source in the +outer iteration. It is typically more efficient to use the single level +iteration scheme, as there is little reason to spend so much work converging the +scattering source if the fission source is not yet converged. + +Overall, the difference in how random ray and Monte Carlo converge the +scattering source means that in practice, random ray typically requires more +inactive iterations than are required in Monte Carlo. While a Monte Carlo +simulation may need 100 inactive iterations to reach a stationary source +distribution for many problems, a random ray solve will likely require 1,000 +iterations or more. Source convergence metrics (e.g., Shannon entropy) are thus +recommended when performing random ray simulations to ascertain when the source +has fully developed. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Converting Angular Flux to Scalar Flux +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Thus far in our derivation, we have been able to write analytical equations that +solve for the change in angular flux of a ray crossing a flat source region +(Equation :eq:`delta_psi`) as well as the ray's average angular flux through +that region (Equation :eq:`average_psi_final`). To determine the source for the +next power iteration, we need to assemble our estimates of angular fluxes from +all the sampled rays into scalar fluxes within each FSR. + +We can define the scalar flux in region :math:`i` as: + +.. math:: + :label: integral + + \phi_i = \frac{\int_{V_i} \int_{4\pi} \psi(r, \Omega) d\Omega d\mathbf{r}}{\int_{V_i} d\mathbf{r}} . + +The integral in the numerator: + +.. math:: + :label: numerator + + \int_{V_i} \int_{4\pi} \psi(r, \Omega) d\Omega d\mathbf{r} . + +is not known analytically, but with random ray, we are going the numerically +approximate it by discretizing over a finite number of tracks (with a finite +number of locations and angles) crossing the domain. We can then use the +characteristic method to determine the total angular flux along that line. + +Conceptually, this can be thought of as taking a volume-weighted sum of angular +fluxes for all :math:`N_i` rays that happen to pass through cell :math:`i` that +iteration. When written in discretized form (with the discretization happening +in terms of individual ray segments :math:`r` that pass through region +:math:`i`), we arrive at: + +.. math:: + :label: discretized + + \phi_{i,g} = \frac{\int_{V_i} \int_{4\pi} \psi(r, \Omega) d\Omega d\mathbf{r}}{\int_{V_i} d\mathbf{r}} = \overline{\overline{\psi}}_{i,g} \approx \frac{\sum\limits_{r=1}^{N_i} \ell_r w_r \overline{\psi}_{r,i,g}}{\sum\limits_{r=1}^{N_i} \ell_r w_r} . + +Here we introduce the term :math:`w_r`, which represents the "weight" of the ray +(its 2D area), such that the volume that a ray is responsible for can be +determined by multiplying its length :math:`\ell` by its weight :math:`w`. As +the scalar flux vector is a shape function only, we are actually free to +multiply all ray weights :math:`w` by any constant such that the overall shape +is still maintained, even if the magnitude of the shape function changes. Thus, +we can simply set :math:`w_r` to be unity for all rays, such that: + +.. math:: + :label: weights + + \text{Volume of cell } i = V_i \approx \sum\limits_{r=1}^{N_i} \ell_r w_r = \sum\limits_{r=1}^{N_i} \ell_r . + +We can then rewrite our discretized equation as: + +.. math:: + :label: discretized_2 + + \phi_{i,g} \approx \frac{\sum\limits_{r=1}^{N_i} \ell_r w_r \overline{\psi}_{r,i,g}}{\sum\limits_{r=1}^{N_i} \ell_r w_r} = \frac{\sum\limits_{r=1}^{N_i} \ell_r \overline{\psi}_{r,i,g}}{\sum\limits_{r=1}^{N_i} \ell_r} . + +Thus, the scalar flux can be inferred if we know the volume weighted sum of the +average angular fluxes that pass through the cell. Substituting +:eq:`average_psi_final` into :eq:`discretized_2`, we arrive at: + +.. math:: + :label: scalar_full + + \phi_{i,g} = \frac{\int_{V_i} \int_{4\pi} \psi(r, \Omega) d\Omega d\mathbf{r}}{\int_{V_i} d\mathbf{r}} = \overline{\overline{\psi}}_{i,g} = \frac{\sum\limits_{r=1}^{N_i} \ell_r \overline{\psi}_{r,i,g}}{\sum\limits_{r=1}^{N_i} \ell_r} = \frac{\sum\limits_{r=1}^{N_i} \ell_r \frac{Q_{i,g}}{\Sigma_{t,i,g}} + \frac{\Delta \psi_{r,g}}{\ell_r \Sigma_{t,i,g}}}{\sum\limits_{r=1}^{N_i} \ell_r}, + +which when partially simplified becomes: + +.. math:: + :label: scalar_four_vols + + \phi = \frac{Q_{i,g} \sum\limits_{r=1}^{N_i} \ell_r}{\Sigma_{t,i,g} \sum\limits_{r=1}^{N_i} \ell_r} + \frac{\sum\limits_{r=1}^{N_i} \ell_r \frac{\Delta \psi_i}{\ell_r}}{\Sigma_{t,i,g} \sum\limits_{r=1}^{N_i} \ell_r} . + +Note that there are now four (seemingly identical) volume terms in this equation. + +~~~~~~~~~~~~~~ +Volume Dilemma +~~~~~~~~~~~~~~ + +At first glance, Equation :eq:`scalar_four_vols` appears ripe for cancellation +of terms. Mathematically, such cancellation allows us to arrive at the following +"naive" estimator for the scalar flux: + +.. math:: + :label: phi_naive + + \phi_{i,g}^{naive} = \frac{Q_{i,g} }{\Sigma_{t,i,g}} + \frac{\sum\limits_{r=1}^{N_i} \Delta \psi_{r,g}}{\Sigma_{t,i,g} \sum\limits_{r=1}^{N_i} \ell_r} . + +This derivation appears mathematically sound at first glance but unfortunately +raises a serious issue as discussed in more depth by `Tramm et al. +`_ and `Cosgrove and Tramm `_. Namely, the second +term: + +.. math:: + :label: ratio_estimator + + \frac{\sum\limits_{r=1}^{N_i} \Delta \psi_{r,g}}{\Sigma_{t,i,g} \sum\limits_{r=1}^{N_i} \ell_r} + +features stochastic variables (the sums over random ray lengths and angular +fluxes) in both the numerator and denominator, making it a stochastic ratio +estimator, which is inherently biased. In practice, usage of the naive estimator +does result in a biased, but "consistent" estimator (i.e., it is biased, but +the bias tends towards zero as the sample size increases). Experimentally, the +right answer can be obtained with this estimator, though a very fine ray density +is required to eliminate the bias. + +How might we solve the biased ratio estimator problem? While there is no obvious +way to alter the numerator term (which arises from the characteristic +integration approach itself), there is potentially more flexibility in how we +treat the stochastic term in the denominator, :math:`\sum\limits_{r=1}^{N_i} +\ell_r` . From Equation :eq:`weights` we know that this term can be directly +inferred from the volume of the problem, which does not actually change between +iterations. Thus, an alternative treatment for this "volume" term in the +denominator is to replace the actual stochastically sampled total track length +with the expected value of the total track length. For instance, if the true +volume of the FSR is known (as is the total volume of the full simulation domain +and the total tracklength used for integration that iteration), then we know the +true expected value of the tracklength in that FSR. That is, if a FSR accounts +for 2% of the overall volume of a simulation domain, then we know that the +expected value of tracklength in that FSR will be 2% of the total tracklength +for all rays that iteration. This is a key insight, as it allows us to the +replace the actual tracklength that was accumulated inside that FSR each +iteration with the expected value. + +If we know the analytical volumes, then those can be used to directly compute +the expected value of the tracklength in each cell. However, as the analytical +volumes are not typically known in OpenMC due to the usage of user-defined +constructive solid geometry, we need to source this quantity from elsewhere. An +obvious choice is to simply accumulate the total tracklength through each FSR +across all iterations (batches) and to use that sum to compute the expected +average length per iteration, as: + +.. math:: + :label: sim_estimator + + \sum\limits^{}_{i} \ell_i \approx \frac{\sum\limits^{B}_{b}\sum\limits^{N_i}_{r} \ell_{b,r} }{B} + +where :math:`b` is a single batch in :math:`B` total batches simulated so far. + +In this manner, the expected value of the tracklength will become more refined +as iterations continue, until after many iterations the variance of the +denominator term becomes trivial compared to the numerator term, essentially +eliminating the presence of the stochastic ratio estimator. A "simulation +averaged" estimator is therefore: + +.. math:: + :label: phi_sim + + \phi_{i,g}^{simulation} = \frac{Q_{i,g} }{\Sigma_{t,i,g}} + \frac{\sum\limits_{r=1}^{N_i} \Delta \psi_{r,g}}{\Sigma_{t,i,g} \frac{\sum\limits^{B}_{b}\sum\limits^{N_i}_{r} \ell_{b,r} }{B}} + +In practical terms, the "simulation averaged" estimator is virtually +indistinguishable numerically from use of the true analytical volume to estimate +this term. Note also that the term "simulation averaged" refers only to the +volume/length treatment, the scalar flux estimate itself is computed fully again +each iteration. + +There are some drawbacks to this method. Recall, this denominator volume term +originally stemmed from taking a volume weighted integral of the angular flux, +in which case the denominator served as a normalization term for the numerator +integral in Equation :eq:`integral`. Essentially, we have now used a different +term for the volume in the numerator as compared to the normalizing volume in +the denominator. The inevitable mismatch (due to noise) between these two +quantities results in a significant increase in variance. Notably, the same +problem occurs if using a tracklength estimate based on the analytical volume, +as again the numerator integral and the normalizing denominator integral no +longer match on a per-iteration basis. + +In practice, the simulation averaged method does completely remove the bias, +though at the cost of a notable increase in variance. Empirical testing reveals +that on most problems, the simulation averaged estimator does win out overall in +numerical performance, as a much coarser quadrature can be used resulting in +faster runtimes overall. Thus, OpenMC uses the simulation averaged estimator in +its random ray mode. + +~~~~~~~~~~~~~~~ +Power Iteration +~~~~~~~~~~~~~~~ + +Given a starting source term, we now have a way of computing an estimate of the +scalar flux in each cell by way of transporting rays randomly through the +domain, recording the change in angular flux for the rays into each cell as they +make their traversals, and summing these contributions up as in Equation +:eq:`phi_sim`. How then do we turn this into an iterative process such that we +improve the estimate of the source and scalar flux over many iterations, given +that our initial starting source will just be a guess? + +The source :math:`Q^{n}` for iteration :math:`n` can be inferred +from the scalar flux from the previous iteration :math:`n-1` as: + +.. math:: + :label: source_update + + Q^{n}(i, g) = \frac{\chi}{k^{n-1}_{eff}} \nu \Sigma_f(i, g) \phi^{n-1}(g) + \sum\limits^{G}_{g'} \Sigma_{s}(i,g,g') \phi^{n-1}(g') + +where :math:`Q^{n}(i, g)` is the total source (fission + scattering) in region +:math:`i` and energy group :math:`g`. Notably, the in-scattering source in group +:math:`g` must be computed by summing over the contributions from all groups +:math:`g' \in G`. + +In a similar manner, the eigenvalue for iteration :math:`n` can be computed as: + +.. math:: + :label: eigenvalue_update + + k^{n}_{eff} = k^{n-1}_{eff} \frac{F^n}{F^{n-1}}, + +where the total spatial- and energy-integrated fission rate :math:`F^n` in +iteration :math:`n` can be computed as: + +.. math:: + :label: fission_source + + F^n = \sum\limits^{M}_{i} \left( V_i \sum\limits^{G}_{g} \nu \Sigma_f(i, g) \phi^{n}(g) \right) + +where :math:`M` is the total number of FSRs in the simulation. Similarly, the +total spatial- and energy-integrated fission rate :math:`F^{n-1}` in iteration +:math:`n-1` can be computed as: + +.. math:: + :label: fission_source_prev + + F^{n-1} = \sum\limits^{M}_{i} \left( V_i \sum\limits^{G}_{g} \nu \Sigma_f(i, g) \phi^{n-1}(g) \right) + +Notably, the volume term :math:`V_i` appears in the eigenvalue update equation. +The same logic applies to the treatment of this term as was discussed earlier. +In OpenMC, we use the "simulation averaged" volume derived from summing over all +ray tracklength contributions to a FSR over all iterations and dividing by the +total integration tracklength to date. Thus, Equation :eq:`fission_source` +becomes: + +.. math:: + :label: fission_source_volumed + + F^n = \sum\limits^{M}_{i} \left( \frac{\sum\limits^{B}_{b}\sum\limits^{N_i}_{r} \ell_{b,r} }{B} \sum\limits^{G}_{g} \nu \Sigma_f(i, g) \phi^{n}(g) \right) + +and a similar substitution can be made to update Equation +:eq:`fission_source_prev` . In OpenMC, the most up-to-date version of the volume +estimate is used, such that the total fission source from the previous iteration +(:math:`n-1`) is also recomputed each iteration. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Ray Starting Conditions and Inactive Length +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Another key area of divergence between deterministic MOC and random ray is the +starting conditions for rays. In deterministic MOC, the angular flux spectrum +for rays are stored at any reflective or periodic boundaries so as to provide a +starting condition for the next iteration. As there are many tracks, storage of +angular fluxes can become costly in terms of memory consumption unless there are +only vacuum boundaries present. + +In random ray, as the starting locations of rays are sampled anew each +iteration, the initial angular flux spectrum for the ray is unknown. While a +guess can be made by taking the isotropic source from the FSR the ray was +sampled in, direct usage of this quantity would result in significant bias and +error being imparted on the simulation. + +Thus, an `on-the-fly approximation method `_ was developed (known +as the "dead zone"), where the first several mean free paths of a ray are +considered to be "inactive" or "read only". In this sense, the angular flux is +solved for using the MOC equation, but the ray does not "tally" any scalar flux +back to the FSRs that it travels through. After several mean free paths have +been traversed, the ray's angular flux spectrum typically becomes dominated by +the accumulated source terms from the cells it has traveled through, while the +(incorrect) starting conditions have been attenuated away. In the animation in +the :ref:`introductory section on this page `, the +yellow portion of the ray lengths is the dead zone. As can be seen in this +animation, the tallied :math:`\sum\limits_{r=1}^{N_i} \Delta \psi_{r,g}` term +that is plotted is not affected by the ray when the ray is within its inactive +length. Only when the ray enters its active mode does the ray contribute to the +:math:`\sum\limits_{r=1}^{N_i} \Delta \psi_{r,g}` sum for the iteration. + +~~~~~~~~~~~~~~~~~~~~~ +Ray Ending Conditions +~~~~~~~~~~~~~~~~~~~~~ + +To ensure that a uniform density of rays is integrated in space and angle +throughout the simulation domain, after exiting the initial inactive "dead zone" +portion of the ray, the rays are run for a user-specified distance. Typically, a +choice of at least several times the length of the inactive "dead zone" is made +so as to amortize the cost of the dead zone. For example, if a dead zone of 30 +cm is selected, then an active length of 300 cm might be selected so that the +cost of the dead zone is at most 10% of the overall runtime. + +-------------------- +Simplified Algorithm +-------------------- + +A simplified set of functions that execute a single random ray power iteration +are given below. Not all global variables are defined in this illustrative +example, but the high level components of the algorithm are shown. A number of +significant simplifications are made for clarity---for example, no inactive +"dead zone" length is shown, geometry operations are abstracted, no parallelism +(or thread safety) is expressed, a naive exponential treatment is used, and rays +are not halted at their exact termination distances, among other subtleties. +Nonetheless, the below algorithms may be useful for gaining intuition on the +basic components of the random ray process. Rather than expressing the algorithm +in abstract pseudocode, C++ is used to make the control flow easier to +understand. + +The first block below shows the logic for a single power iteration (batch): + +.. code-block:: C++ + + double power_iteration(double k_eff) { + + // Update source term (scattering + fission) + update_neutron_source(k_eff); + + // Reset scalar fluxes to zero + fill(global::scalar_flux_new, 0.0f); + + // Transport sweep over all random rays for the iteration + for (int i = 0; i < nrays; i++) { + RandomRay ray; + initialize_ray(ray); + transport_single_ray(ray); + } + + // Normalize scalar flux and update volumes + normalize_scalar_flux_and_volumes(); + + // Add source to scalar flux, compute number of FSR hits + add_source_to_scalar_flux(); + + // Compute k-eff using updated scalar flux + k_eff = compute_k_eff(k_eff); + + // Set phi_old = phi_new + global::scalar_flux_old.swap(global::scalar_flux_new); + + return k_eff; + } + +The second function shows the logic for transporting a single ray within the +transport loop: + +.. code-block:: C++ + + void transport_single_ray(RandomRay& ray) { + + // Reset distance to zero + double distance = 0.0; + + // Continue transport of ray until active length is reached + while (distance < user_setting::active_length) { + // Ray trace to find distance to next surface (i.e., segment length) + double s = distance_to_nearest_boundary(ray); + + // Attenuate flux (and accumulate source/attenuate) on segment + attenuate_flux(ray, s); + + // Advance particle to next surface + ray.location = ray.location + s * ray.direction; + + // Move ray across the surface + cross_surface(ray); + + // Add segment length "s" to total distance traveled + distance += s; + } + } + +The final function below shows the logic for solving for the characteristic MOC +equation (and accumulating the scalar flux contribution of the ray into the +scalar flux value for the FSR). + +.. code-block:: C++ + + void attenuate_flux(RandomRay& ray, double s) { + + // Determine which flat source region (FSR) the ray is currently in + int fsr = get_fsr_id(ray.location); + + // Determine material type + int material = get_material_type(fsr); + + // MOC incoming flux attenuation + source contribution/attenuation equation + for (int e = 0; e < global::n_energy_groups; e++) { + float sigma_t = global::macro_xs[material].total; + float tau = sigma_t * s; + float delta_psi = (ray.angular_flux[e] - global::source[fsr][e] / sigma_t) * (1 - exp(-tau)); + ray.angular_flux_[e] -= delta_psi; + global::scalar_flux_new[fsr][e] += delta_psi; + } + + // Record total tracklength in this FSR (to compute volume) + global::volume[fsr] += s; + } + +------------------------ +How are Tallies Handled? +------------------------ + +Most tallies, filters, and scores that you would expect to work with a +multigroup solver like random ray should work. For example, you can define 3D +mesh tallies with energy filters and flux, fission, and nu-fission scores, etc. +There are some restrictions though. For starters, it is assumed that all filter +mesh boundaries will conform to physical surface boundaries (or lattice +boundaries) in the simulation geometry. It is acceptable for multiple cells +(FSRs) to be contained within a filter mesh cell (e.g., pincell-level or +assembly-level tallies should work), but it is currently left as undefined +behavior if a single simulation cell is able to score to multiple filter mesh +cells. In the future, the capability to fully support mesh tallies may be added +to OpenMC, but for now this restriction needs to be respected. + +--------------------------- +Fundamental Sources of Bias +--------------------------- + +Compared to continuous energy Monte Carlo simulations, the known sources of bias +in random ray particle transport are: + + - **Multigroup Energy Discretization:** The multigroup treatment of flux and + cross sections incurs a significant bias, as a reaction rate (:math:`R_g = + V \phi_g \Sigma_g`) for an energy group :math:`g` can only be conserved + for a given choice of multigroup cross section :math:`\Sigma_g` if the + flux (:math:`\phi_g`) is known a priori. If the flux was already known, + then there would be no point to the simulation, resulting in a fundamental + need for approximating this quantity. There are numerous methods for + generating relatively accurate multigroup cross section libraries that can + each be applied to a narrow design area reliably, although there are + always limitations and/or complexities that arise with a multigroup energy + treatment. This is by far the most significant source of simulation bias + between Monte Carlo and random ray for most problems. While the other + areas typically have solutions that are highly effective at mitigating + bias, error stemming from multigroup energy discretization is much harder + to remedy. + - **Flat Source Approximation:**. In OpenMC, a "flat" (0th order) source + approximation is made, wherein the scattering and fission sources within a + cell are assumed to be spatially uniform. As the source in reality is a + continuous function, this leads to bias, although the bias can be reduced + to acceptable levels if the flat source regions are sufficiently small. + The bias can also be mitigated by assuming a higher-order source (e.g., + linear or quadratic), although OpenMC does not yet have this capability. + In practical terms, this source of bias can become very large if cells are + large (with dimensions beyond that of a typical particle mean free path), + but the subdivision of cells can often reduce this bias to trivial levels. + - **Anisotropic Source Approximation:** In OpenMC, the source is not only + assumed to be flat but also isotropic, leading to bias. It is possible for + MOC (and likely random ray) to treat anisotropy explicitly, but this is + not currently supported in OpenMC. This source of bias is not significant + for some problems, but becomes more problematic for others. Even in the + absence of explicit treatment of anistropy, use of transport-corrected + multigroup cross sections can often mitigate this bias, particularly for + light water reactor simulation problems. + - **Angular Flux Initial Conditions:** Each time a ray is sampled, its + starting angular flux is unknown, so a guess must be made (typically the + source term for the cell it starts in). Usage of an adequate inactive ray + length (dead zone) mitigates this error. As the starting guess is + attenuated at a rate of :math:`\exp(-\Sigma_t \ell)`, this bias can driven + below machine precision in a low cost manner on many problems. + +.. _Tramm-2017a: https://doi.org/10.1016/j.jcp.2017.04.038 +.. _Tramm-2017b: https://doi.org/10.1016/j.anucene.2017.10.015 +.. _Tramm-2018: https://dspace.mit.edu/handle/1721.1/119038 +.. _Tramm-2020: https://doi.org/10.1051/EPJCONF/202124703021 +.. _Cosgrove-2023: https://doi.org/10.1080/00295639.2023.2270618 + +.. only:: html + + .. rubric:: References + +.. [Askew-1972] Askew, “A Characteristics Formulation of the Neutron Transport + Equation in Complicated Geometries.” Technical Report AAEW-M 1108, UK Atomic + Energy Establishment (1972). diff --git a/docs/source/usersguide/data.rst b/docs/source/usersguide/data.rst index 48003ecb70b..6af2973388b 100644 --- a/docs/source/usersguide/data.rst +++ b/docs/source/usersguide/data.rst @@ -279,6 +279,8 @@ The `official ENDF/B-VII.1 HDF5 library multipole library, so if you are using this library, the windowed multipole data will already be available to you. +.. _create_mgxs: + ------------------------- Multigroup Cross Sections ------------------------- diff --git a/docs/source/usersguide/index.rst b/docs/source/usersguide/index.rst index 511bdc6cef0..03a77e87063 100644 --- a/docs/source/usersguide/index.rst +++ b/docs/source/usersguide/index.rst @@ -25,4 +25,6 @@ essential aspects of using OpenMC to perform simulations. processing parallel volume + random_ray troubleshoot + \ No newline at end of file diff --git a/docs/source/usersguide/random_ray.rst b/docs/source/usersguide/random_ray.rst new file mode 100644 index 00000000000..dad86c826e0 --- /dev/null +++ b/docs/source/usersguide/random_ray.rst @@ -0,0 +1,480 @@ +.. _random_ray: + +================= +Random Ray Solver +================= + +In general, the random ray solver mode uses most of the same settings and +:ref:`run strategies ` as the standard Monte Carlo solver +mode. For instance, random ray solves are also split up into :ref:`inactive and +active batches `. However, there are a couple of settings +that are unique to the random ray solver and a few areas that the random ray +run strategy differs, both of which will be described in this section. + +------------------------ +Enabling Random Ray Mode +------------------------ + +To utilize the random ray solver, the :attr:`~openmc.Settings.random_ray` +dictionary must be present in the :class:`openmc.Settings` Python class. There +are a number of additional settings that must be specified within this +dictionary that will be discussed below. Additionally, the "multi-group" energy +mode must be specified. + +------- +Batches +------- + +In Monte Carlo simulations, inactive batches are used to let the fission source +develop into a stationary distribution before active batches are performed that +actually accumulate statistics. While this is true of random ray as well, in the +random ray mode the inactive batches are also used to let the scattering source +develop. Monte Carlo fully represents the scattering source within each +iteration (by its nature of fully simulating particles from birth to death +through any number of physical scattering events), whereas the scattering source +in random ray can only represent as many scattering events as batches have been +completed. For example, by iteration 10 in random ray, the scattering source +only captures the behavior of neutrons through their 10th scattering event. +Thus, while inactive batches are only required in an eigenvalue solve in Monte +Carlo, **inactive batches are required for both eigenvalue and fixed source +solves in random ray mode** due to this additional need to converge the +scattering source. + +The additional burden of converging the scattering source generally results in a +higher requirement for the number of inactive batches---often by an order of +magnitude or more. For instance, it may be reasonable to only use 50 inactive +batches for a light water reactor simulation with Monte Carlo, but random ray +might require 500 or more inactive batches. Similar to Monte Carlo, +:ref:`Shannon entropy ` can be used to gauge whether the +combined scattering and fission source has fully developed. + +Similar to Monte Carlo, active batches are used in the random ray solver mode to +accumulate and converge statistics on unknown quantities (i.e., the random ray +sources, scalar fluxes, as well as any user-specified tallies). + +The batch parameters are set in the same manner as with the regular Monte Carlo +solver:: + + settings = openmc.Settings() + settings.energy_mode = "multi-group" + settings.batches = 1200 + settings.inactive = 600 + +------------------------------- +Inactive Ray Length (Dead Zone) +------------------------------- + +A major issue with random ray is that the starting angular flux distribution for +each sampled ray is unknown. Thus, an on-the-fly method is used to build a high +quality approximation of the angular flux of the ray each iteration. This is +accomplished by running the ray through an inactive length (also known as a dead +zone length), where the ray is moved through the geometry and its angular flux +is solved for via the normal :ref:`MOC ` equation, but +no information is written back to the system. Thus, the ray is run in a "read +only" mode for the set inactive length. This parameter can be adjusted, in units +of cm, as:: + + settings.random_ray['distance_inactive'] = 40.0 + +After several mean free paths are traversed, the angular flux spectrum of the +ray becomes dominated by the in-scattering and fission source components that it +picked up when travelling through the geometry, while its original (incorrect) +starting angular flux is attenuated toward zero. Thus, longer selections of +inactive ray length will asymptotically approach the true angular flux. + +In practice, 10 mean free paths are sufficient (with light water reactors often +requiring only about 10--50 cm of inactive ray length for the error to become +undetectable). However, we caution that certain models with large quantities of +void regions (even if just limited to a few streaming channels) may require +significantly longer inactive ray lengths to ensure that the angular flux is +accurate before the conclusion of the inactive ray length. Additionally, +problems where a sensitive estimate of the uncollided flux is required (e.g., +the detector response to fast neutrons is required, and the detected is located +far away from the source in a moderator region) may require the user to specify +an inactive length that is derived from the pyhsical geometry of the simulation +problem rather than its material properties. For instance, consider a detector +placed 30 cm outside of a reactor core, with a moderator region separating the +detector from the core. In this case, rays sampled in the moderator region and +heading toward the detector will begin life with a highly scattered thermal +spectrum and will have an inaccurate fast spectrum. If the dead zone length is +only 20 cm, we might imagine such rays writing to the detector tally within +their active lengths, despite their innaccurate estimate of the uncollided fast +angular flux. Thus, an inactive length of 100--200 cm would ensure that any such +rays would still be within their inactive regions, and only rays that have +actually traversed through the core (and thus have an accurate representation of +the core's emitted fast flux) will score to the detector region while in their +active phase. + + +------------------------------------ +Active Ray Length and Number of Rays +------------------------------------ + +Once the inactive length of the ray has completed, the active region of the ray +begins. The ray is now run in regular mode, where changes in angular flux as it +traverses through each flat source region are written back to the system, so as +to contribute to the estimate for the iteration scalar flux (which is used to +compute the source for the next iteration). The active ray length can be +adjusted, in units of [cm], as:: + + settings.random_ray['distance_active'] = 400.0 + +Assuming that a sufficient inactive ray length is used so that the starting +angular flux is highly accurate, any selection of active length greater than +zero is theoretically acceptable. However, in order to adequately sample the +full integration domain, a selection of a very short track length would require +a very high number of rays to be selected. Due to the static costs per ray of +computing the starting angular flux in the dead zone, typically very short ray +lengths are undesireable. Thus, to amortize the per-ray cost of the inactive +region of the ray, it is desirable to select a very long inactive ray length. +For example, if the inactive length is set to 20 cm, a 200 cm active ray length +ensures that only about 10% of the overall simulation runtime is spent in the +inactive ray phase integration, making the dead zone a relatively inexpensive +way of estimating the angular flux. + +Thus, to fully amortize the cost of the dead zone integration, one might ask why +not simply run a single ray per iteration with an extremely long active length? +While this is also theoretically possible, this results in two issues. The first +problem is that each ray only represents a single angular sample. As we want to +sample the angular phase space of the simulation with similar fidelity to the +spatial phase space, we naturally want a lot of angles. This means in practice, +we want to balance the need to amortize the cost of the inactive region of the +ray with the need to sample lots of angles. The second problem is that +parallelism in OpenMC is expressed in terms of rays, with each being processed +by an independent MPI rank and/or OpenMP thread, thus we want to ensure each +thread has many rays to process. + +In practical terms, the best strategy is typically to set an active ray length +that is about 10 times that of the inactive ray length. This is often the right +balance between ensuring not too much time is spent in the dead zone, while +still adequately sampling the angular phase space. However, as discussed in the +previous section, some types of simulation may demand that additional thought be +applied to this parameter. For instance, in the same example where we have a +detector region far outside a reactor core, we want to make sure that there is +enough active ray length that rays exiting the core can reach the detector +region. For example, if the detector were to be 30 cm outside of the core, then +we would need to ensure that at least a few hundred cm of active length were +used so as to ensure even rays with indirect angles will be able to reach the +target region. + +The number of rays each iteration can be set by reusing the normal Monte Carlo +particle count selection parameter, as:: + + settings.particles = 2000 + +----------- +Ray Density +----------- + +In the preceding sections, it was argued that for most use cases, the inactive +length for a ray can be determined by taking a multiple of the mean free path +for the limiting energy group. The active ray length could then be set by taking +a multiple of the inactive length. With these parameters set, how many rays per +iteration should be run? + +There are three basic settings that control the density of the stochastic +quadrature being used to integrate the domain each iteration. These three +variables are: + +- The number of rays (in OpenMC settings parlance, "particles") +- The inactive distance per ray +- The active distance per ray + +While the inactive and active ray lengths can usually be chosen by simply +examining the geometry, tallies, and cross section data, one has much more +flexibility in the choice of the number of rays to run. Consider a few +scenarios: + +- If a choice of zero rays is made, then no information is gained by the system + after each batch. +- If a choice of rays close to zero is made, then some information is gained + after each batch, but many source regions may not have been visited that + iteration, which is not ideal numerically and can result in instability. + Empirically, we have found that the simulation can remain stable and produce + accurate results even when on average 20% or more of the cells have zero rays + passing through them each iteration. However, besides the cost of transporting + rays, a new neutron source must be computed based on the scalar flux at each + iteration. This cost is dictated only by the number of source regions and + energy groups---it is independent of the number of rays. Thus, in practical + terms, if too few rays are run, then the simulation runtime becomes dominated + by the fixed cost of source updates, making it inefficient overall given that + a huge number of active batches will likely be required to converge statistics + to acceptable levels. Additionally, if many cells are missed each iteration, + then the fission and scattering sources may not develop very quickly, + resulting in a need for far more inactive batches than might otherwise be + required. +- If a choice of running a very large number of rays is made such that you + guarantee that all cells are hit each iteration, this avoids any issues with + numerical instability. As even more rays are run, this reduces the number of + active batches that must be used to converge statistics and therefore + minimizes the fixed per-iteration source update costs. While this seems + advantageous, it has the same practical downside as with Monte Carlo---namely, + that the inactive batches tend to be overly well integrated, resulting in a + lot of wasted time. This issue is actually much more serious than in Monte + Carlo (where typically only tens of inactive batches are needed), as random + ray often requires hundreds or even thousands of inactive batches. Thus, + minimizing the cost of the source updates in the active phase needs to be + balanced against the increased cost of the inactive phase of the simulation. +- If a choice of rays is made such that relatively few (e.g., around 0.1%) of + cells are missed each iteration, the cost of the inactive batches of the + simulation is minimized. In this "goldilocks" regime, there is very little + chance of numerical instability, and enough information is gained by each cell + to progress the fission and scattering sources forward at their maximum rate. + However, the inactive batches can proceed with minimal cost. While this will + result in the active phase of the simulation requiring more batches (and + correspondingly higher source update costs), the added cost is typically far + less than the savings by making the inactive phase much cheaper. + +To help you set this parameter, OpenMC will report the average flat source +region miss rate at the end of the simulation. Additionally, OpenMC will alert +you if very high miss rates are detected, indicating that more rays and/or a +longer active ray length might improve numerical performance. Thus, a "guess and +check" approach to this parameter is recommended, where a very low guess is +made, a few iterations are performed, and then the simulation is restarted with +a larger value until the "low ray density" messages go away. + +.. note:: + In summary, the user should select an inactive length corresponding to many + times the mean free path of a particle, generally O(10--100) cm, to ensure accuracy of + the starting angular flux. The active length should be 10× the inactive + length to amortize its cost. The number of rays should be enough so that + nearly all :ref:`FSRs ` are hit at least once each power iteration (the hit fraction + is reported by OpenMC for empirical user adjustment). + +.. warning:: + For simulations where long range uncollided flux estimates need to be + accurately resolved (e.g., shielding, detector response, and problems with + significant void areas), make sure that selections for inactive and active + ray lengths are sufficiently long to allow for transport to occur between + source and target regions of interest. + +---------- +Ray Source +---------- + +Random ray requires that the ray source be uniform in space and isotropic in +angle. To facilitate sampling, the user must specify a single random ray source +for sampling rays in both eigenvalue and fixed source solver modes. The random +ray integration source should be of type :class:`openmc.IndependentSource`, and +is specified as part of the :attr:`openmc.Settings.random_ray` dictionary. Note +that the source must not be limited to only fissionable regions. Additionally, +the source box must cover the entire simulation domain. In the case of a +simulation domain that is not box shaped, a box source should still be used to +bound the domain but with the source limited to rejection sampling the actual +simulation universe (which can be specified via the ``domains`` field of the +:class:`openmc.IndependentSource` Python class). Similar to Monte Carlo sources, +for two-dimensional problems (e.g., a 2D pincell) it is desirable to make the +source bounded near the origin of the infinite dimension. An example of an +acceptable ray source for a two-dimensional 2x2 lattice would look like: + +:: + + pitch = 1.26 + lower_left = (-pitch, -pitch, -pitch) + upper_right = ( pitch, pitch, pitch) + uniform_dist = openmc.stats.Box(lower_left, upper_right) + settings.random_ray['ray_source'] = openmc.IndependentSource(space=uniform_dist) + +.. note:: + The random ray source is not related to the underlying particle flux or + source distribution of the simulation problem. It is akin to the selection + of an integration quadrature. Thus, in fixed source mode, the ray source + still needs to be provided and still needs to be uniform in space and angle + throughout the simulation domain. In fixed source mode, the user will + provide physical particle fixed sources in addition to the random ray + source. + +.. _subdivision_fsr: + +---------------------------------- +Subdivision of Flat Source Regions +---------------------------------- + +While the scattering and fission sources in Monte Carlo +are treated continuously, they are assumed to be invariant (flat) within a +MOC or random ray flat source region (FSR). This introduces bias into the +simulation, which can be remedied by reducing the physical size of the FSR +to dimensions below that of typical mean free paths of particles. + +In OpenMC, this subdivision currently must be done manually. The level of +subdivision needed will be dependent on the fidelity the user requires. For +typical light water reactor analysis, consider the following example subdivision +of a two-dimensional 2x2 reflective pincell lattice: + +.. figure:: ../_images/2x2_materials.jpeg + :class: with-border + :width: 400 + + Material definition for an asymmetrical 2x2 lattice (1.26 cm pitch) + +.. figure:: ../_images/2x2_fsrs.jpeg + :class: with-border + :width: 400 + + FSR decomposition for an asymmetrical 2x2 lattice (1.26 cm pitch) + +In the future, automated subdivision of FSRs via mesh overlay may be supported. + +------- +Tallies +------- + +Most tallies, filters, and scores that you would expect to work with a +multigroup solver like random ray are supported. For example, you can define 3D +mesh tallies with energy filters and flux, fission, and nu-fission scores, etc. +There are some restrictions though. For starters, it is assumed that all filter +mesh boundaries will conform to physical surface boundaries (or lattice +boundaries) in the simulation geometry. It is acceptable for multiple cells +(FSRs) to be contained within a mesh element (e.g., pincell-level or +assembly-level tallies should work), but it is currently left as undefined +behavior if a single simulation cell is contained in multiple mesh elements. + +Supported scores: + - flux + - total + - fission + - nu-fission + - events + +Supported Estimators: + - tracklength + +Supported Filters: + - cell + - cell instance + - distribcell + - energy + - material + - mesh + - universe + +Note that there is no difference between the analog, tracklength, and collision +estimators in random ray mode as individual particles are not being simulated. +Tracklength-style tally estimation is inherent to the random ray method. + +-------- +Plotting +-------- + +Visualization of geometry is handled in the same way as normal with OpenMC (see +:ref:`plotting guide ` for more details). That is, ``openmc +--plot`` is handled without any modifications, as the random ray solver uses the +same geometry definition as in Monte Carlo. + +In addition to OpenMC's standard geometry plotting mode, the random ray solver +also features an additional method of data visualization. If a ``plots.xml`` +file is present, any voxel plots that are defined will be output at the end of a +random ray simulation. Rather than being stored in HDF5 file format, the random +ray plotting will generate ``.vtk`` files that can be directly read and plotted +with `Paraview `_. + +In fixed source Monte Carlo (MC) simulations, by default the only thing global +tally provided is the leakage fraction. In a k-eigenvalue MC simulation, by +default global tallies are collected for the eigenvalue and leakage fraction. +Spatial flux information must be manually requested, and often fine-grained +spatial meshes are considered costly/unnecessary, so it is impractical in MC +mode to plot spatial flux or power info by default. Conversely, in random ray, +the solver functions by estimating the multigroup source and flux spectrums in +every fine-grained FSR each iteration. Thus, for random ray, in both fixed +source and eigenvalue simulations, the simulation always finishes with a well +converged flux estimate for all areas. As such, it is much more common in random +ray, MOC, and other deterministic codes to provide spatial flux information by +default. In the future, all FSR data will be made available in the statepoint +file, which facilitates plotting and manipulation through the Python API; at +present, statepoint support is not available. + +Only voxel plots will be used to generate output; other plot types present in +the ``plots.xml`` file will be ignored. The following fields will be written to +the VTK structured grid file: + + - material + - FSR index + - flux spectrum (for each energy group) + - total fission source (integrated across all energy groups) + +------------------------------------------ +Inputting Multigroup Cross Sections (MGXS) +------------------------------------------ + +Multigroup cross sections for use with OpenMC's random ray solver are input the +same way as with OpenMC's traditional multigroup Monte Carlo mode. There is more +information on generating multigroup cross sections via OpenMC in the +:ref:`multigroup materials ` user guide. You may also wish to +use an existing multigroup library. An example of using OpenMC's Python +interface to generate a correctly formatted ``mgxs.h5`` input file is given +in the `OpenMC Jupyter notebook collection +`_. + +.. note:: + Currently only isotropic and isothermal multigroup cross sections are + supported in random ray mode. To represent multiple material temperatures, + separate materials can be defined each with a separate multigroup dataset + corresponding to a given temperature. + +--------------------------------------- +Putting it All Together: Example Inputs +--------------------------------------- + +An example of a settings definition for random ray is given below:: + + # Geometry and MGXS material definition of 2x2 lattice (not shown) + pitch = 1.26 + group_edges = [1e-5, 0.0635, 10.0, 1.0e2, 1.0e3, 0.5e6, 1.0e6, 20.0e6] + ... + + # Instantiate a settings object for a random ray solve + settings = openmc.Settings() + settings.energy_mode = "multi-group" + settings.batches = 1200 + settings.inactive = 600 + settings.particles = 2000 + + settings.random_ray['distance_inactive'] = 40.0 + settings.random_ray['distance_active'] = 400.0 + + # Create an initial uniform spatial source distribution for sampling rays + lower_left = (-pitch, -pitch, -pitch) + upper_right = ( pitch, pitch, pitch) + uniform_dist = openmc.stats.Box(lower_left, upper_right) + settings.random_ray['ray_source'] = openmc.IndependentSource(space=uniform_dist) + + settings.export_to_xml() + + # Define tallies + + # Create a mesh filter + mesh = openmc.RegularMesh() + mesh.dimension = (2, 2) + mesh.lower_left = (-pitch/2, -pitch/2) + mesh.upper_right = (pitch/2, pitch/2) + mesh_filter = openmc.MeshFilter(mesh) + + # Create a multigroup energy filter + energy_filter = openmc.EnergyFilter(group_edges) + + # Create tally using our two filters and add scores + tally = openmc.Tally() + tally.filters = [mesh_filter, energy_filter] + tally.scores = ['flux', 'fission', 'nu-fission'] + + # Instantiate a Tallies collection and export to XML + tallies = openmc.Tallies([tally]) + tallies.export_to_xml() + + # Create voxel plot + plot = openmc.Plot() + plot.origin = [0, 0, 0] + plot.width = [2*pitch, 2*pitch, 1] + plot.pixels = [1000, 1000, 1] + plot.type = 'voxel' + + # Instantiate a Plots collection and export to XML + plots = openmc.Plots([plot]) + plots.export_to_xml() + +All other inputs (e.g., geometry, materials) will be unchanged from a typical +Monte Carlo run (see the :ref:`geometry ` and +:ref:`multigroup materials ` user guides for more information). + +There is also a complete example of a pincell available in the +``openmc/examples/pincell_random_ray`` folder. diff --git a/examples/pincell_random_ray/build_xml.py b/examples/pincell_random_ray/build_xml.py new file mode 100644 index 00000000000..b3dd8020a51 --- /dev/null +++ b/examples/pincell_random_ray/build_xml.py @@ -0,0 +1,203 @@ +import numpy as np +import openmc +import openmc.mgxs + +############################################################################### +# Create multigroup data + +# Instantiate the energy group data +group_edges = [1e-5, 0.0635, 10.0, 1.0e2, 1.0e3, 0.5e6, 1.0e6, 20.0e6] +groups = openmc.mgxs.EnergyGroups(group_edges) + +# Instantiate the 7-group (C5G7) cross section data +uo2_xsdata = openmc.XSdata('UO2', groups) +uo2_xsdata.order = 0 +uo2_xsdata.set_total( + [0.1779492, 0.3298048, 0.4803882, 0.5543674, 0.3118013, 0.3951678, + 0.5644058]) +uo2_xsdata.set_absorption([8.0248e-03, 3.7174e-03, 2.6769e-02, 9.6236e-02, + 3.0020e-02, 1.1126e-01, 2.8278e-01]) +scatter_matrix = np.array( + [[[0.1275370, 0.0423780, 0.0000094, 0.0000000, 0.0000000, 0.0000000, 0.0000000], + [0.0000000, 0.3244560, 0.0016314, 0.0000000, 0.0000000, 0.0000000, 0.0000000], + [0.0000000, 0.0000000, 0.4509400, 0.0026792, 0.0000000, 0.0000000, 0.0000000], + [0.0000000, 0.0000000, 0.0000000, 0.4525650, 0.0055664, 0.0000000, 0.0000000], + [0.0000000, 0.0000000, 0.0000000, 0.0001253, 0.2714010, 0.0102550, 0.0000000], + [0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0012968, 0.2658020, 0.0168090], + [0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0085458, 0.2730800]]]) +scatter_matrix = np.rollaxis(scatter_matrix, 0, 3) +uo2_xsdata.set_scatter_matrix(scatter_matrix) +uo2_xsdata.set_fission([7.21206e-03, 8.19301e-04, 6.45320e-03, + 1.85648e-02, 1.78084e-02, 8.30348e-02, + 2.16004e-01]) +uo2_xsdata.set_nu_fission([2.005998e-02, 2.027303e-03, 1.570599e-02, + 4.518301e-02, 4.334208e-02, 2.020901e-01, + 5.257105e-01]) +uo2_xsdata.set_chi([5.8791e-01, 4.1176e-01, 3.3906e-04, 1.1761e-07, 0.0000e+00, + 0.0000e+00, 0.0000e+00]) + +h2o_xsdata = openmc.XSdata('LWTR', groups) +h2o_xsdata.order = 0 +h2o_xsdata.set_total([0.15920605, 0.412969593, 0.59030986, 0.58435, + 0.718, 1.2544497, 2.650379]) +h2o_xsdata.set_absorption([6.0105e-04, 1.5793e-05, 3.3716e-04, + 1.9406e-03, 5.7416e-03, 1.5001e-02, + 3.7239e-02]) +scatter_matrix = np.array( + [[[0.0444777, 0.1134000, 0.0007235, 0.0000037, 0.0000001, 0.0000000, 0.0000000], + [0.0000000, 0.2823340, 0.1299400, 0.0006234, 0.0000480, 0.0000074, 0.0000010], + [0.0000000, 0.0000000, 0.3452560, 0.2245700, 0.0169990, 0.0026443, 0.0005034], + [0.0000000, 0.0000000, 0.0000000, 0.0910284, 0.4155100, 0.0637320, 0.0121390], + [0.0000000, 0.0000000, 0.0000000, 0.0000714, 0.1391380, 0.5118200, 0.0612290], + [0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0022157, 0.6999130, 0.5373200], + [0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.1324400, 2.4807000]]]) +scatter_matrix = np.rollaxis(scatter_matrix, 0, 3) +h2o_xsdata.set_scatter_matrix(scatter_matrix) + +mg_cross_sections_file = openmc.MGXSLibrary(groups) +mg_cross_sections_file.add_xsdatas([uo2_xsdata, h2o_xsdata]) +mg_cross_sections_file.export_to_hdf5() + +############################################################################### +# Create materials for the problem + +# Instantiate some Materials and register the appropriate macroscopic data +uo2 = openmc.Material(name='UO2 fuel') +uo2.set_density('macro', 1.0) +uo2.add_macroscopic('UO2') + +water = openmc.Material(name='Water') +water.set_density('macro', 1.0) +water.add_macroscopic('LWTR') + +# Instantiate a Materials collection and export to XML +materials_file = openmc.Materials([uo2, water]) +materials_file.cross_sections = "mgxs.h5" +materials_file.export_to_xml() + +############################################################################### +# Define problem geometry + +# The geometry we will define a simplified pincell with fuel radius 0.54 cm +# surrounded by moderator (same as in the multigroup example). +# In random ray, we typically want several radial regions and azimuthal +# sectors in both the fuel and moderator areas of the pincell. This is +# due to the flat source approximation requiring that source regions are +# small compared to the typical mean free path of a neutron. Below we +# sudivide the basic pincell into 8 aziumthal sectors (pizza slices) and +# 5 concentric rings in both the fuel and moderator. + +# TODO: When available in OpenMC, use cylindrical lattice instead to +# simplify definition and improve runtime performance. + +pincell_base = openmc.Universe() + +# These are the subdivided radii (creating 5 concentric regions in the +# fuel and moderator) +ring_radii = [0.241, 0.341, 0.418, 0.482, 0.54, 0.572, 0.612, 0.694, 0.786] +fills = [uo2, uo2, uo2, uo2, uo2, water, water, water, water, water] + +# We then create cells representing the bounded rings, with special +# treatment for both the innermost and outermost cells +cells = [] +for r in range(10): + cell = [] + if r == 0: + outer_bound = openmc.ZCylinder(r=ring_radii[r]) + cell = openmc.Cell(fill=fills[r], region=-outer_bound) + elif r == 9: + inner_bound = openmc.ZCylinder(r=ring_radii[r-1]) + cell = openmc.Cell(fill=fills[r], region=+inner_bound) + else: + inner_bound = openmc.ZCylinder(r=ring_radii[r-1]) + outer_bound = openmc.ZCylinder(r=ring_radii[r]) + cell = openmc.Cell(fill=fills[r], region=+inner_bound & -outer_bound) + pincell_base.add_cell(cell) + +# We then generate 8 planes to bound 8 azimuthal sectors +azimuthal_planes = [] +for i in range(8): + angle = 2 * i * openmc.pi / 8 + normal_vector = (-openmc.sin(angle), openmc.cos(angle), 0) + azimuthal_planes.append(openmc.Plane(a=normal_vector[0], b=normal_vector[1], c=normal_vector[2], d=0)) + +# Create a cell for each azimuthal sector using the pincell base class +azimuthal_cells = [] +for i in range(8): + azimuthal_cell = openmc.Cell(name=f'azimuthal_cell_{i}') + azimuthal_cell.fill = pincell_base + azimuthal_cell.region = +azimuthal_planes[i] & -azimuthal_planes[(i+1) % 8] + azimuthal_cells.append(azimuthal_cell) + +# Create the (subdivided) geometry with the azimuthal universes +pincell = openmc.Universe(cells=azimuthal_cells) + +# Create a region represented as the inside of a rectangular prism +pitch = 1.26 +box = openmc.model.RectangularPrism(pitch, pitch, boundary_type='reflective') +pincell_bounded = openmc.Cell(fill=pincell, region=-box, name='pincell') + +# Create a geometry (specifying merge surfaces option to remove +# all the redundant cylinder/plane surfaces) and export to XML +geometry = openmc.Geometry([pincell_bounded], merge_surfaces=True) +geometry.export_to_xml() + +############################################################################### +# Define problem settings + +# Instantiate a Settings object, set all runtime parameters, and export to XML +settings = openmc.Settings() +settings.energy_mode = "multi-group" +settings.batches = 600 +settings.inactive = 300 +settings.particles = 50 + +# Create an initial uniform spatial source distribution for sampling rays. +# Note that this must be uniform in space and angle. +lower_left = (-pitch/2, -pitch/2, -1) +upper_right = (pitch/2, pitch/2, 1) +uniform_dist = openmc.stats.Box(lower_left, upper_right) +settings.random_ray['ray_source'] = openmc.IndependentSource(space=uniform_dist) +settings.random_ray['distance_inactive'] = 40.0 +settings.random_ray['distance_active'] = 400.0 + +settings.export_to_xml() + +############################################################################### +# Define tallies + +# Create a mesh that will be used for tallying +mesh = openmc.RegularMesh() +mesh.dimension = (2, 2) +mesh.lower_left = (-pitch/2, -pitch/2) +mesh.upper_right = (pitch/2, pitch/2) + +# Create a mesh filter that can be used in a tally +mesh_filter = openmc.MeshFilter(mesh) + +# Let's also create a filter to measure each group +# indepdendently +energy_filter = openmc.EnergyFilter(group_edges) + +# Now use the mesh filter in a tally and indicate what scores are desired +tally = openmc.Tally(name="Mesh and Energy tally") +tally.filters = [mesh_filter, energy_filter] +tally.scores = ['flux', 'fission', 'nu-fission'] + +# Instantiate a Tallies collection and export to XML +tallies = openmc.Tallies([tally]) +tallies.export_to_xml() + +############################################################################### +# Exporting to OpenMC plots.xml file +############################################################################### + +plot = openmc.Plot() +plot.origin = [0, 0, 0] +plot.width = [pitch, pitch, pitch] +plot.pixels = [1000, 1000, 1] +plot.type = 'voxel' + +# Instantiate a Plots collection and export to XML +plots = openmc.Plots([plot]) +plots.export_to_xml() diff --git a/include/openmc/boundary_condition.h b/include/openmc/boundary_condition.h index e63e232e9a4..cd8988162f2 100644 --- a/include/openmc/boundary_condition.h +++ b/include/openmc/boundary_condition.h @@ -10,6 +10,7 @@ namespace openmc { // Forward declare some types used in function arguments. class Particle; +class RandomRay; class Surface; //============================================================================== diff --git a/include/openmc/cell.h b/include/openmc/cell.h index c405f536b5d..e68443a32fd 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -249,6 +249,42 @@ class Cell { std::unordered_map> get_contained_cells( int32_t instance = 0, Position* hint = nullptr) const; + //! Determine the material index corresponding to a specific cell instance, + //! taking into account presence of distribcell material + //! \param[in] instance of the cell + //! \return material index + int32_t material(int32_t instance) const + { + // If distributed materials are used, then each instance has its own + // material definition. If distributed materials are not used, then + // all instances used the same material stored at material_[0]. The + // presence of distributed materials is inferred from the size of + // the material_ vector being greater than one. + if (material_.size() > 1) { + return material_[instance]; + } else { + return material_[0]; + } + } + + //! Determine the temperature index corresponding to a specific cell instance, + //! taking into account presence of distribcell temperature + //! \param[in] instance of the cell + //! \return temperature index + double sqrtkT(int32_t instance) const + { + // If distributed materials are used, then each instance has its own + // temperature definition. If distributed materials are not used, then + // all instances used the same temperature stored at sqrtkT_[0]. The + // presence of distributed materials is inferred from the size of + // the sqrtkT_ vector being greater than one. + if (sqrtkT_.size() > 1) { + return sqrtkT_[instance]; + } else { + return sqrtkT_[0]; + } + } + protected: //! Determine the path to this cell instance in the geometry hierarchy //! \param[in] instance of the cell to find parent cells for diff --git a/include/openmc/constants.h b/include/openmc/constants.h index ba558b04089..1c683e5f50c 100644 --- a/include/openmc/constants.h +++ b/include/openmc/constants.h @@ -340,6 +340,8 @@ enum class RunMode { VOLUME }; +enum class SolverType { MONTE_CARLO, RANDOM_RAY }; + //============================================================================== // Geometry Constants diff --git a/include/openmc/mgxs.h b/include/openmc/mgxs.h index d77c34bd5f5..3fb0608104f 100644 --- a/include/openmc/mgxs.h +++ b/include/openmc/mgxs.h @@ -29,7 +29,6 @@ class Mgxs { int num_delayed_groups; // number of delayed neutron groups vector xs; // Cross section data // MGXS Incoming Flux Angular grid information - bool is_isotropic; // used to skip search for angle indices if isotropic int n_pol; int n_azi; vector polar; @@ -85,6 +84,8 @@ class Mgxs { std::string name; // name of dataset, e.g., UO2 double awr; // atomic weight ratio bool fissionable; // Is this fissionable + bool is_isotropic { + true}; // used to skip search for angle indices if isotropic Mgxs() = default; diff --git a/include/openmc/output.h b/include/openmc/output.h index 1ef95a88792..1ece3de960c 100644 --- a/include/openmc/output.h +++ b/include/openmc/output.h @@ -57,6 +57,8 @@ void print_results(); void write_tallies(); +void show_time(const char* label, double secs, int indent_level = 0); + } // namespace openmc #endif // OPENMC_OUTPUT_H @@ -80,4 +82,4 @@ struct formatter> { } }; -} // namespace fmt \ No newline at end of file +} // namespace fmt diff --git a/include/openmc/plot.h b/include/openmc/plot.h index 7b66036fb71..ee6c3fbec58 100644 --- a/include/openmc/plot.h +++ b/include/openmc/plot.h @@ -100,6 +100,7 @@ class PlottableInterface { virtual void print_info() const = 0; const std::string& path_plot() const { return path_plot_; } + std::string& path_plot() { return path_plot_; } int id() const { return id_; } int level() const { return level_; } diff --git a/include/openmc/random_ray/flat_source_domain.h b/include/openmc/random_ray/flat_source_domain.h new file mode 100644 index 00000000000..5f64914edb9 --- /dev/null +++ b/include/openmc/random_ray/flat_source_domain.h @@ -0,0 +1,141 @@ +#ifndef OPENMC_RANDOM_RAY_FLAT_SOURCE_DOMAIN_H +#define OPENMC_RANDOM_RAY_FLAT_SOURCE_DOMAIN_H + +#include "openmc/openmp_interface.h" +#include "openmc/position.h" + +namespace openmc { + +/* + * The FlatSourceDomain class encompasses data and methods for storing + * scalar flux and source region for all flat source regions in a + * random ray simulation domain. + */ + +class FlatSourceDomain { +public: + //---------------------------------------------------------------------------- + // Helper Structs + + // A mapping object that is used to map between a specific random ray + // source region and an OpenMC native tally bin that it should score to + // every iteration. + struct TallyTask { + int tally_idx; + int filter_idx; + int score_idx; + int score_type; + TallyTask(int tally_idx, int filter_idx, int score_idx, int score_type) + : tally_idx(tally_idx), filter_idx(filter_idx), score_idx(score_idx), + score_type(score_type) + {} + }; + + //---------------------------------------------------------------------------- + // Constructors + FlatSourceDomain(); + + //---------------------------------------------------------------------------- + // Methods + void update_neutron_source(double k_eff); + double compute_k_eff(double k_eff_old) const; + void normalize_scalar_flux_and_volumes( + double total_active_distance_per_iteration); + int64_t add_source_to_scalar_flux(); + void batch_reset(); + void convert_source_regions_to_tallies(); + void random_ray_tally() const; + void accumulate_iteration_flux(); + void output_to_vtk() const; + void all_reduce_replicated_source_regions(); + + //---------------------------------------------------------------------------- + // Public Data members + + bool mapped_all_tallies_ {false}; // If all source regions have been visited + + int64_t n_source_regions_ {0}; // Total number of source regions in the model + + // 1D array representing source region starting offset for each OpenMC Cell + // in model::cells + vector source_region_offsets_; + + // 1D arrays representing values for all source regions + vector lock_; + vector was_hit_; + vector volume_; + vector position_recorded_; + vector position_; + + // 2D arrays stored in 1D representing values for all source regions x energy + // groups + vector scalar_flux_old_; + vector scalar_flux_new_; + vector source_; + + //---------------------------------------------------------------------------- + // Private data members +private: + int negroups_; // Number of energy groups in simulation + int64_t n_source_elements_ {0}; // Total number of source regions in the model + // times the number of energy groups + + // 2D array representing values for all source regions x energy groups x tally + // tasks + vector> tally_task_; + + // 1D arrays representing values for all source regions + vector material_; + vector volume_t_; + + // 2D arrays stored in 1D representing values for all source regions x energy + // groups + vector scalar_flux_final_; + +}; // class FlatSourceDomain + +//============================================================================ +//! Non-member functions +//============================================================================ + +// Returns the inputted value in big endian byte ordering. If the system is +// little endian, the byte ordering is flipped. If the system is big endian, +// the inputted value is returned as is. This function is necessary as +// .vtk binary files use big endian byte ordering. +template +T convert_to_big_endian(T in) +{ + // 4 byte integer + uint32_t test = 1; + + // 1 byte pointer to first byte of test integer + uint8_t* ptr = reinterpret_cast(&test); + + // If the first byte of test is 0, then the system is big endian. In this + // case, we don't have to do anything as .vtk files are big endian + if (*ptr == 0) + return in; + + // Otherwise, the system is in little endian, so we need to flip the + // endianness + uint8_t* orig = reinterpret_cast(&in); + uint8_t swapper[sizeof(T)]; + for (int i = 0; i < sizeof(T); i++) { + swapper[i] = orig[sizeof(T) - i - 1]; + } + T out = *reinterpret_cast(&swapper); + return out; +} + +template +void parallel_fill(vector& arr, T value) +{ +#pragma omp parallel for schedule(static) + for (int i = 0; i < arr.size(); i++) { + arr[i] = value; + } +} + +} // namespace openmc + +#endif // OPENMC_RANDOM_RAY_FLAT_SOURCE_DOMAIN_H diff --git a/include/openmc/random_ray/random_ray.h b/include/openmc/random_ray/random_ray.h new file mode 100644 index 00000000000..c114007c631 --- /dev/null +++ b/include/openmc/random_ray/random_ray.h @@ -0,0 +1,55 @@ +#ifndef OPENMC_RANDOM_RAY_H +#define OPENMC_RANDOM_RAY_H + +#include "openmc/memory.h" +#include "openmc/particle.h" +#include "openmc/random_ray/flat_source_domain.h" +#include "openmc/source.h" + +namespace openmc { + +/* + * The RandomRay class encompasses data and methods for transporting random rays + * through the model. It is a small extension of the Particle class. + */ + +// TODO: Inherit from GeometryState instead of Particle +class RandomRay : public Particle { +public: + //---------------------------------------------------------------------------- + // Constructors + RandomRay(); + RandomRay(uint64_t ray_id, FlatSourceDomain* domain); + + //---------------------------------------------------------------------------- + // Methods + void event_advance_ray(); + void attenuate_flux(double distance, bool is_active); + void initialize_ray(uint64_t ray_id, FlatSourceDomain* domain); + uint64_t transport_history_based_single_ray(); + + //---------------------------------------------------------------------------- + // Static data members + static double distance_inactive_; // Inactive (dead zone) ray length + static double distance_active_; // Active ray length + static unique_ptr ray_source_; // Starting source for ray sampling + + //---------------------------------------------------------------------------- + // Public data members + vector angular_flux_; + + //---------------------------------------------------------------------------- + // Private data members +private: + FlatSourceDomain* domain_ {nullptr}; // pointer to domain that has flat source + // data needed for ray transport + vector delta_psi_; + double distance_travelled_ {0}; + int negroups_; + bool is_active_ {false}; + bool is_alive_ {true}; +}; // class RandomRay + +} // namespace openmc + +#endif // OPENMC_RANDOM_RAY_H diff --git a/include/openmc/random_ray/random_ray_simulation.h b/include/openmc/random_ray/random_ray_simulation.h new file mode 100644 index 00000000000..cde0d27dff2 --- /dev/null +++ b/include/openmc/random_ray/random_ray_simulation.h @@ -0,0 +1,59 @@ +#ifndef OPENMC_RANDOM_RAY_SIMULATION_H +#define OPENMC_RANDOM_RAY_SIMULATION_H + +#include "openmc/random_ray/flat_source_domain.h" + +namespace openmc { + +/* + * The RandomRaySimulation class encompasses data and methods for running a + * random ray simulation. + */ + +class RandomRaySimulation { +public: + //---------------------------------------------------------------------------- + // Constructors + RandomRaySimulation(); + + //---------------------------------------------------------------------------- + // Methods + void simulate(); + void reduce_simulation_statistics(); + void output_simulation_results() const; + void instability_check( + int64_t n_hits, double k_eff, double& avg_miss_rate) const; + void print_results_random_ray(uint64_t total_geometric_intersections, + double avg_miss_rate, int negroups, int64_t n_source_regions) const; + + //---------------------------------------------------------------------------- + // Data members +private: + // Contains all flat source region data + FlatSourceDomain domain_; + + // Random ray eigenvalue + double k_eff_ {1.0}; + + // Tracks the average FSR miss rate for analysis and reporting + double avg_miss_rate_ {0.0}; + + // Tracks the total number of geometric intersections by all rays for + // reporting + uint64_t total_geometric_intersections_ {0}; + + // Number of energy groups + int negroups_; + +}; // class RandomRaySimulation + +//============================================================================ +//! Non-member functions +//============================================================================ + +void openmc_run_random_ray(); +void validate_random_ray_inputs(); + +} // namespace openmc + +#endif // OPENMC_RANDOM_RAY_SIMULATION_H diff --git a/include/openmc/settings.h b/include/openmc/settings.h index 5e60009bcd7..b71ec364931 100644 --- a/include/openmc/settings.h +++ b/include/openmc/settings.h @@ -112,8 +112,9 @@ extern ResScatMethod res_scat_method; //!< resonance upscattering method extern double res_scat_energy_min; //!< Min energy in [eV] for res. upscattering extern double res_scat_energy_max; //!< Max energy in [eV] for res. upscattering extern vector - res_scat_nuclides; //!< Nuclides using res. upscattering treatment -extern RunMode run_mode; //!< Run mode (eigenvalue, fixed src, etc.) + res_scat_nuclides; //!< Nuclides using res. upscattering treatment +extern RunMode run_mode; //!< Run mode (eigenvalue, fixed src, etc.) +extern SolverType solver_type; //!< Solver Type (Monte Carlo or Random Ray) extern std::unordered_set sourcepoint_batch; //!< Batches when source should be written extern std::unordered_set @@ -139,6 +140,7 @@ extern int trigger_batch_interval; //!< Batch interval for triggers extern "C" int verbosity; //!< How verbose to make output extern double weight_cutoff; //!< Weight cutoff for Russian roulette extern double weight_survive; //!< Survival weight after Russian roulette + } // namespace settings //============================================================================== diff --git a/include/openmc/timer.h b/include/openmc/timer.h index 62b97883f40..d928aad4560 100644 --- a/include/openmc/timer.h +++ b/include/openmc/timer.h @@ -31,6 +31,7 @@ extern Timer time_event_advance_particle; extern Timer time_event_surface_crossing; extern Timer time_event_collision; extern Timer time_event_death; +extern Timer time_update_src; } // namespace simulation diff --git a/openmc/settings.py b/openmc/settings.py index 828d5aef44f..63124602908 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -86,7 +86,8 @@ class Settings: .. versionadded:: 0.12 rel_max_lost_particles : float - Maximum number of lost particles, relative to the total number of particles + Maximum number of lost particles, relative to the total number of + particles .. versionadded:: 0.12 inactive : int @@ -146,6 +147,18 @@ class Settings: Initial seed for randomly generated plot colors. ptables : bool Determine whether probability tables are used. + random_ray : dict + Options for configuring the random ray solver. Acceptable keys are: + + :distance_inactive: + Indicates the total active distance in [cm] a ray should travel + :distance_active: + Indicates the total active distance in [cm] a ray should travel + :ray_source: + Starting ray distribution (must be uniform in space and angle) as + specified by a :class:`openmc.SourceBase` object. + + .. versionadded:: 0.14.1 resonance_scattering : dict Settings for resonance elastic scattering. Accepted keys are 'enable' (bool), 'method' (str), 'energy_min' (float), 'energy_max' (float), and @@ -153,10 +166,10 @@ class Settings: rejection correction) or 'rvs' (relative velocity sampling). If not specified, 'rvs' is the default method. The 'energy_min' and 'energy_max' values indicate the minimum and maximum energies above and - below which the resonance elastic scattering method is to be - applied. The 'nuclides' list indicates what nuclides the method should - be applied to. In its absence, the method will be applied to all - nuclides with 0 K elastic scattering data present. + below which the resonance elastic scattering method is to be applied. + The 'nuclides' list indicates what nuclides the method should be applied + to. In its absence, the method will be applied to all nuclides with 0 K + elastic scattering data present. run_mode : {'eigenvalue', 'fixed source', 'plot', 'volume', 'particle restart'} The type of calculation to perform (default is 'eigenvalue') seed : int @@ -185,26 +198,26 @@ class Settings: :surface_ids: List of surface ids at which crossing particles are to be banked (int) - :max_particles: Maximum number of particles to be banked on - surfaces per process (int) + :max_particles: Maximum number of particles to be banked on surfaces per + process (int) :mcpl: Output in the form of an MCPL-file (bool) survival_biasing : bool Indicate whether survival biasing is to be used tabular_legendre : dict Determines if a multi-group scattering moment kernel expanded via Legendre polynomials is to be converted to a tabular distribution or - not. Accepted keys are 'enable' and 'num_points'. The value for - 'enable' is a bool stating whether the conversion to tabular is - performed; the value for 'num_points' sets the number of points to use - in the tabular distribution, should 'enable' be True. + not. Accepted keys are 'enable' and 'num_points'. The value for 'enable' + is a bool stating whether the conversion to tabular is performed; the + value for 'num_points' sets the number of points to use in the tabular + distribution, should 'enable' be True. temperature : dict Defines a default temperature and method for treating intermediate temperatures at which nuclear data doesn't exist. Accepted keys are 'default', 'method', 'range', 'tolerance', and 'multipole'. The value for 'default' should be a float representing the default temperature in Kelvin. The value for 'method' should be 'nearest' or 'interpolation'. - If the method is 'nearest', 'tolerance' indicates a range of - temperature within which cross sections may be used. If the method is + If the method is 'nearest', 'tolerance' indicates a range of temperature + within which cross sections may be used. If the method is 'interpolation', 'tolerance' indicates the range of temperatures outside of the available cross section temperatures where cross sections will evaluate to the nearer bound. The value for 'range' should be a pair of @@ -348,6 +361,8 @@ def __init__(self, **kwargs): self._max_splits = None self._max_tracks = None + self._random_ray = {} + for key, value in kwargs.items(): setattr(self, key, value) @@ -1030,6 +1045,31 @@ def weight_window_generators(self, wwgs): wwgs = [wwgs] self._weight_window_generators = cv.CheckedList(WeightWindowGenerator, 'weight window generators', wwgs) + @property + def random_ray(self) -> dict: + return self._random_ray + + @random_ray.setter + def random_ray(self, random_ray: dict): + if not isinstance(random_ray, Mapping): + raise ValueError(f'Unable to set random_ray from "{random_ray}" ' + 'which is not a dict.') + for key in random_ray: + if key == 'distance_active': + cv.check_type('active ray length', random_ray[key], Real) + cv.check_greater_than('active ray length', random_ray[key], 0.0) + elif key == 'distance_inactive': + cv.check_type('inactive ray length', random_ray[key], Real) + cv.check_greater_than('inactive ray length', + random_ray[key], 0.0, True) + elif key == 'ray_source': + cv.check_type('random ray source', random_ray[key], SourceBase) + else: + raise ValueError(f'Unable to set random ray to "{key}" which is ' + 'unsupported by OpenMC') + + self._random_ray = random_ray + def _create_run_mode_subelement(self, root): elem = ET.SubElement(root, "run_mode") elem.text = self._run_mode.value @@ -1442,6 +1482,17 @@ def _create_max_tracks_subelement(self, root): elem = ET.SubElement(root, "max_tracks") elem.text = str(self._max_tracks) + def _create_random_ray_subelement(self, root): + if self._random_ray: + element = ET.SubElement(root, "random_ray") + for key, value in self._random_ray.items(): + if key == 'ray_source' and isinstance(value, SourceBase): + source_element = value.to_xml_element() + element.append(source_element) + else: + subelement = ET.SubElement(element, key) + subelement.text = str(value) + def _eigenvalue_from_xml_element(self, root): elem = root.find('eigenvalue') if elem is not None: @@ -1793,6 +1844,17 @@ def _max_tracks_from_xml_element(self, root): if text is not None: self.max_tracks = int(text) + def _random_ray_from_xml_element(self, root): + elem = root.find('random_ray') + if elem is not None: + self.random_ray = {} + for child in elem: + if child.tag in ('distance_inactive', 'distance_active'): + self.random_ray[child.tag] = float(child.text) + elif child.tag == 'source': + source = SourceBase.from_xml_element(child) + self.random_ray['ray_source'] = source + def to_xml_element(self, mesh_memo=None): """Create a 'settings' element to be written to an XML file. @@ -1855,6 +1917,7 @@ def to_xml_element(self, mesh_memo=None): self._create_weight_window_checkpoints_subelement(element) self._create_max_splits_subelement(element) self._create_max_tracks_subelement(element) + self._create_random_ray_subelement(element) # Clean the indentation in the file to be user-readable clean_indentation(element) @@ -1958,6 +2021,7 @@ def from_xml_element(cls, elem, meshes=None): settings._weight_window_checkpoints_from_xml_element(elem) settings._max_splits_from_xml_element(elem) settings._max_tracks_from_xml_element(elem) + settings._random_ray_from_xml_element(elem) # TODO: Get volume calculations return settings diff --git a/src/boundary_condition.cpp b/src/boundary_condition.cpp index 42a8e27a164..b58054dce8c 100644 --- a/src/boundary_condition.cpp +++ b/src/boundary_condition.cpp @@ -6,6 +6,7 @@ #include "openmc/constants.h" #include "openmc/error.h" +#include "openmc/random_ray/random_ray.h" #include "openmc/surface.h" namespace openmc { @@ -16,7 +17,18 @@ namespace openmc { void VacuumBC::handle_particle(Particle& p, const Surface& surf) const { - p.cross_vacuum_bc(surf); + // Random ray and Monte Carlo need different treatments at vacuum BCs + if (settings::solver_type == SolverType::RANDOM_RAY) { + // Reflect ray off of the surface + ReflectiveBC().handle_particle(p, surf); + + // Set ray's angular flux spectrum to vacuum conditions (zero) + RandomRay* r = static_cast(&p); + std::fill(r->angular_flux_.begin(), r->angular_flux_.end(), 0.0); + + } else { + p.cross_vacuum_bc(surf); + } } //============================================================================== diff --git a/src/eigenvalue.cpp b/src/eigenvalue.cpp index 5584210a1fc..d5410094b18 100644 --- a/src/eigenvalue.cpp +++ b/src/eigenvalue.cpp @@ -57,16 +57,28 @@ void calculate_generation_keff() double keff_reduced; #ifdef OPENMC_MPI - // Combine values across all processors - MPI_Allreduce(&simulation::keff_generation, &keff_reduced, 1, MPI_DOUBLE, - MPI_SUM, mpi::intracomm); + if (settings::solver_type != SolverType::RANDOM_RAY) { + // Combine values across all processors + MPI_Allreduce(&simulation::keff_generation, &keff_reduced, 1, MPI_DOUBLE, + MPI_SUM, mpi::intracomm); + } else { + // If using random ray, MPI parallelism is provided by domain replication. + // As such, all fluxes will be reduced at the end of each transport sweep, + // such that all ranks have identical scalar flux vectors, and will all + // independently compute the same value of k. Thus, there is no need to + // perform any additional MPI reduction here. + keff_reduced = simulation::keff_generation; + } #else keff_reduced = simulation::keff_generation; #endif // Normalize single batch estimate of k // TODO: This should be normalized by total_weight, not by n_particles - keff_reduced /= settings::n_particles; + if (settings::solver_type != SolverType::RANDOM_RAY) { + keff_reduced /= settings::n_particles; + } + simulation::k_generation.push_back(keff_reduced); } @@ -370,7 +382,8 @@ int openmc_get_keff(double* k_combined) // Special case for n <=3. Notice that at the end, // there is a N-3 term in a denominator. - if (simulation::n_realizations <= 3) { + if (simulation::n_realizations <= 3 || + settings::solver_type == SolverType::RANDOM_RAY) { k_combined[0] = simulation::keff; k_combined[1] = simulation::keff_std; if (simulation::n_realizations <= 1) { diff --git a/src/geometry.cpp b/src/geometry.cpp index a16addd4848..445b19faac1 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -174,17 +174,9 @@ bool find_cell_inner( // Set the material and temperature. p.material_last() = p.material(); - if (c.material_.size() > 1) { - p.material() = c.material_[p.cell_instance()]; - } else { - p.material() = c.material_[0]; - } + p.material() = c.material(p.cell_instance()); p.sqrtkT_last() = p.sqrtkT(); - if (c.sqrtkT_.size() > 1) { - p.sqrtkT() = c.sqrtkT_[p.cell_instance()]; - } else { - p.sqrtkT() = c.sqrtkT_[0]; - } + p.sqrtkT() = c.sqrtkT(p.cell_instance()); return true; diff --git a/src/main.cpp b/src/main.cpp index 02a850ead84..88251ac7232 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,6 +6,7 @@ #include "openmc/error.h" #include "openmc/message_passing.h" #include "openmc/particle_restart.h" +#include "openmc/random_ray/random_ray_simulation.h" #include "openmc/settings.h" int main(int argc, char* argv[]) @@ -31,7 +32,15 @@ int main(int argc, char* argv[]) switch (settings::run_mode) { case RunMode::FIXED_SOURCE: case RunMode::EIGENVALUE: - err = openmc_run(); + switch (settings::solver_type) { + case SolverType::MONTE_CARLO: + err = openmc_run(); + break; + case SolverType::RANDOM_RAY: + openmc_run_random_ray(); + err = 0; + break; + } break; case RunMode::PLOTTING: err = openmc_plot_geometry(); diff --git a/src/mesh.cpp b/src/mesh.cpp index bc6781ad313..c6e421b4290 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -582,7 +582,7 @@ void StructuredMesh::raytrace_mesh( // Compute the length of the entire track. double total_distance = (r1 - r0).norm(); - if (total_distance == 0.0) + if (total_distance == 0.0 && settings::solver_type != SolverType::RANDOM_RAY) return; const int n = n_dimension_; diff --git a/src/output.cpp b/src/output.cpp index 9b4171d8d11..b1b963f7d3c 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -31,6 +31,7 @@ #include "openmc/mgxs_interface.h" #include "openmc/nuclide.h" #include "openmc/plot.h" +#include "openmc/random_ray/flat_source_domain.h" #include "openmc/reaction.h" #include "openmc/settings.h" #include "openmc/simulation.h" @@ -409,7 +410,7 @@ void print_generation() //============================================================================== -void show_time(const char* label, double secs, int indent_level = 0) +void show_time(const char* label, double secs, int indent_level) { int width = 33 - indent_level * 2; fmt::print("{0:{1}} {2:<{3}} = {4:>10.4e} seconds\n", "", 2 * indent_level, diff --git a/src/random_ray/flat_source_domain.cpp b/src/random_ray/flat_source_domain.cpp new file mode 100644 index 00000000000..5e1194aa92a --- /dev/null +++ b/src/random_ray/flat_source_domain.cpp @@ -0,0 +1,686 @@ +#include "openmc/random_ray/flat_source_domain.h" + +#include "openmc/cell.h" +#include "openmc/geometry.h" +#include "openmc/message_passing.h" +#include "openmc/mgxs_interface.h" +#include "openmc/output.h" +#include "openmc/plot.h" +#include "openmc/random_ray/random_ray.h" +#include "openmc/simulation.h" +#include "openmc/tallies/filter.h" +#include "openmc/tallies/tally.h" +#include "openmc/tallies/tally_scoring.h" +#include "openmc/timer.h" + +#include + +namespace openmc { + +//============================================================================== +// FlatSourceDomain implementation +//============================================================================== + +FlatSourceDomain::FlatSourceDomain() : negroups_(data::mg.num_energy_groups_) +{ + // Count the number of source regions, compute the cell offset + // indices, and store the material type The reason for the offsets is that + // some cell types may not have material fills, and therefore do not + // produce FSRs. Thus, we cannot index into the global arrays directly + for (const auto& c : model::cells) { + if (c->type_ != Fill::MATERIAL) { + source_region_offsets_.push_back(-1); + } else { + source_region_offsets_.push_back(n_source_regions_); + n_source_regions_ += c->n_instances_; + n_source_elements_ += c->n_instances_ * negroups_; + } + } + + // Initialize cell-wise arrays + lock_.resize(n_source_regions_); + material_.resize(n_source_regions_); + position_recorded_.assign(n_source_regions_, 0); + position_.resize(n_source_regions_); + volume_.assign(n_source_regions_, 0.0); + volume_t_.assign(n_source_regions_, 0.0); + was_hit_.assign(n_source_regions_, 0); + + // Initialize element-wise arrays + scalar_flux_new_.assign(n_source_elements_, 0.0); + scalar_flux_old_.assign(n_source_elements_, 1.0); + scalar_flux_final_.assign(n_source_elements_, 0.0); + source_.resize(n_source_elements_); + tally_task_.resize(n_source_elements_); + + // Initialize material array + int64_t source_region_id = 0; + for (int i = 0; i < model::cells.size(); i++) { + Cell& cell = *model::cells[i]; + if (cell.type_ == Fill::MATERIAL) { + for (int j = 0; j < cell.n_instances_; j++) { + material_[source_region_id++] = cell.material(j); + } + } + } + + // Sanity check + if (source_region_id != n_source_regions_) { + fatal_error("Unexpected number of source regions"); + } +} + +void FlatSourceDomain::batch_reset() +{ + // Reset scalar fluxes, iteration volume tallies, and region hit flags to + // zero + parallel_fill(scalar_flux_new_, 0.0f); + parallel_fill(volume_, 0.0); + parallel_fill(was_hit_, 0); +} + +void FlatSourceDomain::accumulate_iteration_flux() +{ +#pragma omp parallel for + for (int64_t se = 0; se < n_source_elements_; se++) { + scalar_flux_final_[se] += scalar_flux_new_[se]; + } +} + +// Compute new estimate of scattering + fission sources in each source region +// based on the flux estimate from the previous iteration. +void FlatSourceDomain::update_neutron_source(double k_eff) +{ + simulation::time_update_src.start(); + + double inverse_k_eff = 1.0 / k_eff; + + // Temperature and angle indices, if using multiple temperature + // data sets and/or anisotropic data sets. + // TODO: Currently assumes we are only using single temp/single + // angle data. + const int t = 0; + const int a = 0; + +#pragma omp parallel for + for (int sr = 0; sr < n_source_regions_; sr++) { + int material = material_[sr]; + + for (int e_out = 0; e_out < negroups_; e_out++) { + float sigma_t = data::mg.macro_xs_[material].get_xs( + MgxsType::TOTAL, e_out, nullptr, nullptr, nullptr, t, a); + float scatter_source = 0.0f; + float fission_source = 0.0f; + + for (int e_in = 0; e_in < negroups_; e_in++) { + float scalar_flux = scalar_flux_old_[sr * negroups_ + e_in]; + float sigma_s = data::mg.macro_xs_[material].get_xs( + MgxsType::NU_SCATTER, e_in, &e_out, nullptr, nullptr, t, a); + float nu_sigma_f = data::mg.macro_xs_[material].get_xs( + MgxsType::NU_FISSION, e_in, nullptr, nullptr, nullptr, t, a); + float chi = data::mg.macro_xs_[material].get_xs( + MgxsType::CHI_PROMPT, e_in, &e_out, nullptr, nullptr, t, a); + scatter_source += sigma_s * scalar_flux; + fission_source += nu_sigma_f * scalar_flux * chi; + } + + fission_source *= inverse_k_eff; + float new_isotropic_source = (scatter_source + fission_source) / sigma_t; + source_[sr * negroups_ + e_out] = new_isotropic_source; + } + } + + simulation::time_update_src.stop(); +} + +// Normalizes flux and updates simulation-averaged volume estimate +void FlatSourceDomain::normalize_scalar_flux_and_volumes( + double total_active_distance_per_iteration) +{ + float normalization_factor = 1.0 / total_active_distance_per_iteration; + double volume_normalization_factor = + 1.0 / (total_active_distance_per_iteration * simulation::current_batch); + +// Normalize scalar flux to total distance travelled by all rays this iteration +#pragma omp parallel for + for (int64_t e = 0; e < scalar_flux_new_.size(); e++) { + scalar_flux_new_[e] *= normalization_factor; + } + +// Accumulate cell-wise ray length tallies collected this iteration, then +// update the simulation-averaged cell-wise volume estimates +#pragma omp parallel for + for (int64_t sr = 0; sr < n_source_regions_; sr++) { + volume_t_[sr] += volume_[sr]; + volume_[sr] = volume_t_[sr] * volume_normalization_factor; + } +} + +// Combine transport flux contributions and flat source contributions from the +// previous iteration to generate this iteration's estimate of scalar flux. +int64_t FlatSourceDomain::add_source_to_scalar_flux() +{ + int64_t n_hits = 0; + + // Temperature and angle indices, if using multiple temperature + // data sets and/or anisotropic data sets. + // TODO: Currently assumes we are only using single temp/single + // angle data. + const int t = 0; + const int a = 0; + +#pragma omp parallel for reduction(+ : n_hits) + for (int sr = 0; sr < n_source_regions_; sr++) { + + // Check if this cell was hit this iteration + int was_cell_hit = was_hit_[sr]; + if (was_cell_hit) { + n_hits++; + } + + double volume = volume_[sr]; + int material = material_[sr]; + for (int g = 0; g < negroups_; g++) { + int64_t idx = (sr * negroups_) + g; + + // There are three scenarios we need to consider: + if (was_cell_hit) { + // 1. If the FSR was hit this iteration, then the new flux is equal to + // the flat source from the previous iteration plus the contributions + // from rays passing through the source region (computed during the + // transport sweep) + float sigma_t = data::mg.macro_xs_[material].get_xs( + MgxsType::TOTAL, g, nullptr, nullptr, nullptr, t, a); + scalar_flux_new_[idx] /= (sigma_t * volume); + scalar_flux_new_[idx] += source_[idx]; + } else if (volume > 0.0) { + // 2. If the FSR was not hit this iteration, but has been hit some + // previous iteration, then we simply set the new scalar flux to be + // equal to the contribution from the flat source alone. + scalar_flux_new_[idx] = source_[idx]; + } else { + // If the FSR was not hit this iteration, and it has never been hit in + // any iteration (i.e., volume is zero), then we want to set this to 0 + // to avoid dividing anything by a zero volume. + scalar_flux_new_[idx] = 0.0f; + } + } + } + + // Return the number of source regions that were hit this iteration + return n_hits; +} + +// Generates new estimate of k_eff based on the differences between this +// iteration's estimate of the scalar flux and the last iteration's estimate. +double FlatSourceDomain::compute_k_eff(double k_eff_old) const +{ + double fission_rate_old = 0; + double fission_rate_new = 0; + + // Temperature and angle indices, if using multiple temperature + // data sets and/or anisotropic data sets. + // TODO: Currently assumes we are only using single temp/single + // angle data. + const int t = 0; + const int a = 0; + +#pragma omp parallel for reduction(+ : fission_rate_old, fission_rate_new) + for (int sr = 0; sr < n_source_regions_; sr++) { + + // If simulation averaged volume is zero, don't include this cell + double volume = volume_[sr]; + if (volume == 0.0) { + continue; + } + + int material = material_[sr]; + + double sr_fission_source_old = 0; + double sr_fission_source_new = 0; + + for (int g = 0; g < negroups_; g++) { + int64_t idx = (sr * negroups_) + g; + double nu_sigma_f = data::mg.macro_xs_[material].get_xs( + MgxsType::NU_FISSION, g, nullptr, nullptr, nullptr, t, a); + sr_fission_source_old += nu_sigma_f * scalar_flux_old_[idx]; + sr_fission_source_new += nu_sigma_f * scalar_flux_new_[idx]; + } + + fission_rate_old += sr_fission_source_old * volume; + fission_rate_new += sr_fission_source_new * volume; + } + + double k_eff_new = k_eff_old * (fission_rate_new / fission_rate_old); + + return k_eff_new; +} + +// This function is responsible for generating a mapping between random +// ray flat source regions (cell instances) and tally bins. The mapping +// takes the form of a "TallyTask" object, which accounts for one single +// score being applied to a single tally. Thus, a single source region +// may have anywhere from zero to many tally tasks associated with it --- +// meaning that the global "tally_task" data structure is in 2D. The outer +// dimension corresponds to the source element (i.e., each entry corresponds +// to a specific energy group within a specific source region), and the +// inner dimension corresponds to the tallying task itself. Mechanically, +// the mapping between FSRs and spatial filters is done by considering +// the location of a single known ray midpoint that passed through the +// FSR. I.e., during transport, the first ray to pass through a given FSR +// will write down its midpoint for use with this function. This is a cheap +// and easy way of mapping FSRs to spatial tally filters, but comes with +// the downside of adding the restriction that spatial tally filters must +// share boundaries with the physical geometry of the simulation (so as +// not to subdivide any FSR). It is acceptable for a spatial tally region +// to contain multiple FSRs, but not the other way around. + +// TODO: In future work, it would be preferable to offer a more general +// (but perhaps slightly more expensive) option for handling arbitrary +// spatial tallies that would be allowed to subdivide FSRs. + +// Besides generating the mapping structure, this function also keeps track +// of whether or not all flat source regions have been hit yet. This is +// required, as there is no guarantee that all flat source regions will +// be hit every iteration, such that in the first few iterations some FSRs +// may not have a known position within them yet to facilitate mapping to +// spatial tally filters. However, after several iterations, if all FSRs +// have been hit and have had a tally map generated, then this status will +// be passed back to the caller to alert them that this function doesn't +// need to be called for the remainder of the simulation. + +void FlatSourceDomain::convert_source_regions_to_tallies() +{ + openmc::simulation::time_tallies.start(); + + // Tracks if we've generated a mapping yet for all source regions. + bool all_source_regions_mapped = true; + +// Attempt to generate mapping for all source regions +#pragma omp parallel for + for (int sr = 0; sr < n_source_regions_; sr++) { + + // If this source region has not been hit by a ray yet, then + // we aren't going to be able to map it, so skip it. + if (!position_recorded_[sr]) { + all_source_regions_mapped = false; + continue; + } + + // A particle located at the recorded midpoint of a ray + // crossing through this source region is used to estabilish + // the spatial location of the source region + Particle p; + p.r() = position_[sr]; + p.r_last() = position_[sr]; + bool found = exhaustive_find_cell(p); + + // Loop over energy groups (so as to support energy filters) + for (int g = 0; g < negroups_; g++) { + + // Set particle to the current energy + p.g() = g; + p.g_last() = g; + p.E() = data::mg.energy_bin_avg_[p.g()]; + p.E_last() = p.E(); + + int64_t source_element = sr * negroups_ + g; + + // If this task has already been populated, we don't need to do + // it again. + if (tally_task_[source_element].size() > 0) { + continue; + } + + // Loop over all active tallies. This logic is essentially identical + // to what happens when scanning for applicable tallies during + // MC transport. + for (auto i_tally : model::active_tallies) { + Tally& tally {*model::tallies[i_tally]}; + + // Initialize an iterator over valid filter bin combinations. + // If there are no valid combinations, use a continue statement + // to ensure we skip the assume_separate break below. + auto filter_iter = FilterBinIter(tally, p); + auto end = FilterBinIter(tally, true, &p.filter_matches()); + if (filter_iter == end) + continue; + + // Loop over filter bins. + for (; filter_iter != end; ++filter_iter) { + auto filter_index = filter_iter.index_; + auto filter_weight = filter_iter.weight_; + + // Loop over scores + for (auto score_index = 0; score_index < tally.scores_.size(); + score_index++) { + auto score_bin = tally.scores_[score_index]; + // If a valid tally, filter, and score cobination has been found, + // then add it to the list of tally tasks for this source element. + tally_task_[source_element].emplace_back( + i_tally, filter_index, score_index, score_bin); + } + } + } + // Reset all the filter matches for the next tally event. + for (auto& match : p.filter_matches()) + match.bins_present_ = false; + } + } + openmc::simulation::time_tallies.stop(); + + mapped_all_tallies_ = all_source_regions_mapped; +} + +// Tallying in random ray is not done directly during transport, rather, +// it is done only once after each power iteration. This is made possible +// by way of a mapping data structure that relates spatial source regions +// (FSRs) to tally/filter/score combinations. The mechanism by which the +// mapping is done (and the limitations incurred) is documented in the +// "convert_source_regions_to_tallies()" function comments above. The present +// tally function simply traverses the mapping data structure and executes +// the scoring operations to OpenMC's native tally result arrays. + +void FlatSourceDomain::random_ray_tally() const +{ + openmc::simulation::time_tallies.start(); + + // Temperature and angle indices, if using multiple temperature + // data sets and/or anisotropic data sets. + // TODO: Currently assumes we are only using single temp/single + // angle data. + const int t = 0; + const int a = 0; + +// We loop over all source regions and energy groups. For each +// element, we check if there are any scores needed and apply +// them. +#pragma omp parallel for + for (int sr = 0; sr < n_source_regions_; sr++) { + double volume = volume_[sr]; + double material = material_[sr]; + for (int g = 0; g < negroups_; g++) { + int idx = sr * negroups_ + g; + double flux = scalar_flux_new_[idx] * volume; + for (auto& task : tally_task_[idx]) { + double score; + switch (task.score_type) { + + case SCORE_FLUX: + score = flux; + break; + + case SCORE_TOTAL: + score = flux * data::mg.macro_xs_[material].get_xs( + MgxsType::TOTAL, g, NULL, NULL, NULL, t, a); + break; + + case SCORE_FISSION: + score = flux * data::mg.macro_xs_[material].get_xs( + MgxsType::FISSION, g, NULL, NULL, NULL, t, a); + break; + + case SCORE_NU_FISSION: + score = flux * data::mg.macro_xs_[material].get_xs( + MgxsType::NU_FISSION, g, NULL, NULL, NULL, t, a); + break; + + case SCORE_EVENTS: + score = 1.0; + break; + + default: + fatal_error("Invalid score specified in tallies.xml. Only flux, " + "total, fission, nu-fission, and events are supported in " + "random ray mode."); + break; + } + Tally& tally {*model::tallies[task.tally_idx]}; +#pragma omp atomic + tally.results_(task.filter_idx, task.score_idx, TallyResult::VALUE) += + score; + } + } + } +} + +void FlatSourceDomain::all_reduce_replicated_source_regions() +{ +#ifdef OPENMC_MPI + + // If we only have 1 MPI rank, no need + // to reduce anything. + if (mpi::n_procs <= 1) + return; + + simulation::time_bank_sendrecv.start(); + + // The "position_recorded" variable needs to be allreduced (and maxed), + // as whether or not a cell was hit will affect some decisions in how the + // source is calculated in the next iteration so as to avoid dividing + // by zero. We take the max rather than the sum as the hit values are + // expected to be zero or 1. + MPI_Allreduce(MPI_IN_PLACE, position_recorded_.data(), n_source_regions_, + MPI_INT, MPI_MAX, mpi::intracomm); + + // The position variable is more complicated to reduce than the others, + // as we do not want the sum of all positions in each cell, rather, we + // want to just pick any single valid position. Thus, we perform a gather + // and then pick the first valid position we find for all source regions + // that have had a position recorded. This operation does not need to + // be broadcast back to other ranks, as this value is only used for the + // tally conversion operation, which is only performed on the master rank. + // While this is expensive, it only needs to be done for active batches, + // and only if we have not mapped all the tallies yet. Once tallies are + // fully mapped, then the position vector is fully populated, so this + // operation can be skipped. + + // First, we broadcast the fully mapped tally status variable so that + // all ranks are on the same page + int mapped_all_tallies_i = static_cast(mapped_all_tallies_); + MPI_Bcast(&mapped_all_tallies_i, 1, MPI_INT, 0, mpi::intracomm); + + // Then, we perform the gather of position data, if needed + if (simulation::current_batch > settings::n_inactive && + !mapped_all_tallies_i) { + + // Master rank will gather results and pick valid positions + if (mpi::master) { + // Initialize temporary vector for receiving positions + vector> all_position; + all_position.resize(mpi::n_procs); + for (int i = 0; i < mpi::n_procs; i++) { + all_position[i].resize(n_source_regions_); + } + + // Copy master rank data into gathered vector for convenience + all_position[0] = position_; + + // Receive all data into gather vector + for (int i = 1; i < mpi::n_procs; i++) { + MPI_Recv(all_position[i].data(), n_source_regions_ * 3, MPI_DOUBLE, i, + 0, mpi::intracomm, MPI_STATUS_IGNORE); + } + + // Scan through gathered data and pick first valid cell posiiton + for (int sr = 0; sr < n_source_regions_; sr++) { + if (position_recorded_[sr] == 1) { + for (int i = 0; i < mpi::n_procs; i++) { + if (all_position[i][sr].x != 0.0 || all_position[i][sr].y != 0.0 || + all_position[i][sr].z != 0.0) { + position_[sr] = all_position[i][sr]; + break; + } + } + } + } + } else { + // Other ranks just send in their data + MPI_Send(position_.data(), n_source_regions_ * 3, MPI_DOUBLE, 0, 0, + mpi::intracomm); + } + } + + // For the rest of the source region data, we simply perform an all reduce, + // as these values will be needed on all ranks for transport during the + // next iteration. + MPI_Allreduce(MPI_IN_PLACE, volume_.data(), n_source_regions_, MPI_DOUBLE, + MPI_SUM, mpi::intracomm); + + MPI_Allreduce(MPI_IN_PLACE, was_hit_.data(), n_source_regions_, MPI_INT, + MPI_SUM, mpi::intracomm); + + MPI_Allreduce(MPI_IN_PLACE, scalar_flux_new_.data(), n_source_elements_, + MPI_FLOAT, MPI_SUM, mpi::intracomm); + + simulation::time_bank_sendrecv.stop(); +#endif +} + +// Outputs all basic material, FSR ID, multigroup flux, and +// fission source data to .vtk file that can be directly +// loaded and displayed by Paraview. Note that .vtk binary +// files require big endian byte ordering, so endianness +// is checked and flipped if necessary. +void FlatSourceDomain::output_to_vtk() const +{ + // Rename .h5 plot filename(s) to .vtk filenames + for (int p = 0; p < model::plots.size(); p++) { + PlottableInterface* plot = model::plots[p].get(); + plot->path_plot() = + plot->path_plot().substr(0, plot->path_plot().find_last_of('.')) + ".vtk"; + } + + // Print header information + print_plot(); + + // Outer loop over plots + for (int p = 0; p < model::plots.size(); p++) { + + // Get handle to OpenMC plot object and extract params + Plot* openmc_plot = dynamic_cast(model::plots[p].get()); + + // Random ray plots only support voxel plots + if (!openmc_plot) { + warning(fmt::format("Plot {} is invalid plot type -- only voxel plotting " + "is allowed in random ray mode.", + p)); + continue; + } else if (openmc_plot->type_ != Plot::PlotType::voxel) { + warning(fmt::format("Plot {} is invalid plot type -- only voxel plotting " + "is allowed in random ray mode.", + p)); + continue; + } + + int Nx = openmc_plot->pixels_[0]; + int Ny = openmc_plot->pixels_[1]; + int Nz = openmc_plot->pixels_[2]; + Position origin = openmc_plot->origin_; + Position width = openmc_plot->width_; + Position ll = origin - width / 2.0; + double x_delta = width.x / Nx; + double y_delta = width.y / Ny; + double z_delta = width.z / Nz; + std::string filename = openmc_plot->path_plot(); + + // Perform sanity checks on file size + uint64_t bytes = Nx * Ny * Nz * (negroups_ + 1 + 1 + 1) * sizeof(float); + write_message(5, "Processing plot {}: {}... (Estimated size is {} MB)", + openmc_plot->id(), filename, bytes / 1.0e6); + if (bytes / 1.0e9 > 1.0) { + warning("Voxel plot specification is very large (>1 GB). Plotting may be " + "slow."); + } else if (bytes / 1.0e9 > 100.0) { + fatal_error("Voxel plot specification is too large (>100 GB). Exiting."); + } + + // Relate voxel spatial locations to random ray source regions + vector voxel_indices(Nx * Ny * Nz); + +#pragma omp parallel for collapse(3) + for (int z = 0; z < Nz; z++) { + for (int y = 0; y < Ny; y++) { + for (int x = 0; x < Nx; x++) { + Position sample; + sample.z = ll.z + z_delta / 2.0 + z * z_delta; + sample.y = ll.y + y_delta / 2.0 + y * y_delta; + sample.x = ll.x + x_delta / 2.0 + x * x_delta; + Particle p; + p.r() = sample; + bool found = exhaustive_find_cell(p); + int i_cell = p.lowest_coord().cell; + int64_t source_region_idx = + source_region_offsets_[i_cell] + p.cell_instance(); + voxel_indices[z * Ny * Nx + y * Nx + x] = source_region_idx; + } + } + } + + // Open file for writing + std::FILE* plot = std::fopen(filename.c_str(), "wb"); + + // Write vtk metadata + std::fprintf(plot, "# vtk DataFile Version 2.0\n"); + std::fprintf(plot, "Dataset File\n"); + std::fprintf(plot, "BINARY\n"); + std::fprintf(plot, "DATASET STRUCTURED_POINTS\n"); + std::fprintf(plot, "DIMENSIONS %d %d %d\n", Nx, Ny, Nz); + std::fprintf(plot, "ORIGIN 0 0 0\n"); + std::fprintf(plot, "SPACING %lf %lf %lf\n", x_delta, y_delta, z_delta); + std::fprintf(plot, "POINT_DATA %d\n", Nx * Ny * Nz); + + // Plot multigroup flux data + for (int g = 0; g < negroups_; g++) { + std::fprintf(plot, "SCALARS flux_group_%d float\n", g); + std::fprintf(plot, "LOOKUP_TABLE default\n"); + for (int fsr : voxel_indices) { + int64_t source_element = fsr * negroups_ + g; + float flux = scalar_flux_final_[source_element]; + flux /= (settings::n_batches - settings::n_inactive); + flux = convert_to_big_endian(flux); + std::fwrite(&flux, sizeof(float), 1, plot); + } + } + + // Plot FSRs + std::fprintf(plot, "SCALARS FSRs float\n"); + std::fprintf(plot, "LOOKUP_TABLE default\n"); + for (int fsr : voxel_indices) { + float value = future_prn(10, fsr); + value = convert_to_big_endian(value); + std::fwrite(&value, sizeof(float), 1, plot); + } + + // Plot Materials + std::fprintf(plot, "SCALARS Materials int\n"); + std::fprintf(plot, "LOOKUP_TABLE default\n"); + for (int fsr : voxel_indices) { + int mat = material_[fsr]; + mat = convert_to_big_endian(mat); + std::fwrite(&mat, sizeof(int), 1, plot); + } + + // Plot fission source + std::fprintf(plot, "SCALARS total_fission_source float\n"); + std::fprintf(plot, "LOOKUP_TABLE default\n"); + for (int fsr : voxel_indices) { + float total_fission = 0.0; + int mat = material_[fsr]; + for (int g = 0; g < negroups_; g++) { + int64_t source_element = fsr * negroups_ + g; + float flux = scalar_flux_final_[source_element]; + flux /= (settings::n_batches - settings::n_inactive); + float Sigma_f = data::mg.macro_xs_[mat].get_xs( + MgxsType::FISSION, g, nullptr, nullptr, nullptr, 0, 0); + total_fission += Sigma_f * flux; + } + total_fission = convert_to_big_endian(total_fission); + std::fwrite(&total_fission, sizeof(float), 1, plot); + } + + std::fclose(plot); + } +} + +} // namespace openmc diff --git a/src/random_ray/random_ray.cpp b/src/random_ray/random_ray.cpp new file mode 100644 index 00000000000..f471c75517a --- /dev/null +++ b/src/random_ray/random_ray.cpp @@ -0,0 +1,289 @@ +#include "openmc/random_ray/random_ray.h" + +#include "openmc/geometry.h" +#include "openmc/message_passing.h" +#include "openmc/mgxs_interface.h" +#include "openmc/random_ray/flat_source_domain.h" +#include "openmc/search.h" +#include "openmc/settings.h" +#include "openmc/simulation.h" +#include "openmc/source.h" + +namespace openmc { + +//============================================================================== +// Non-method functions +//============================================================================== + +// returns 1 - exp(-tau) +// Equivalent to -(_expm1f(-tau)), but faster +// Written by Colin Josey. +float cjosey_exponential(float tau) +{ + constexpr float c1n = -1.0000013559236386308f; + constexpr float c2n = 0.23151368626911062025f; + constexpr float c3n = -0.061481916409314966140f; + constexpr float c4n = 0.0098619906458127653020f; + constexpr float c5n = -0.0012629460503540849940f; + constexpr float c6n = 0.00010360973791574984608f; + constexpr float c7n = -0.000013276571933735820960f; + + constexpr float c0d = 1.0f; + constexpr float c1d = -0.73151337729389001396f; + constexpr float c2d = 0.26058381273536471371f; + constexpr float c3d = -0.059892419041316836940f; + constexpr float c4d = 0.0099070188241094279067f; + constexpr float c5d = -0.0012623388962473160860f; + constexpr float c6d = 0.00010361277635498731388f; + constexpr float c7d = -0.000013276569500666698498f; + + float x = -tau; + + float den = c7d; + den = den * x + c6d; + den = den * x + c5d; + den = den * x + c4d; + den = den * x + c3d; + den = den * x + c2d; + den = den * x + c1d; + den = den * x + c0d; + + float num = c7n; + num = num * x + c6n; + num = num * x + c5n; + num = num * x + c4n; + num = num * x + c3n; + num = num * x + c2n; + num = num * x + c1n; + num = num * x; + + return num / den; +} + +//============================================================================== +// RandomRay implementation +//============================================================================== + +// Static Variable Declarations +double RandomRay::distance_inactive_; +double RandomRay::distance_active_; +unique_ptr RandomRay::ray_source_; + +RandomRay::RandomRay() + : negroups_(data::mg.num_energy_groups_), + angular_flux_(data::mg.num_energy_groups_), + delta_psi_(data::mg.num_energy_groups_) +{} + +RandomRay::RandomRay(uint64_t ray_id, FlatSourceDomain* domain) : RandomRay() +{ + initialize_ray(ray_id, domain); +} + +// Transports ray until termination criteria are met +uint64_t RandomRay::transport_history_based_single_ray() +{ + using namespace openmc; + while (alive()) { + event_advance_ray(); + if (!alive()) + break; + event_cross_surface(); + } + + return n_event(); +} + +// Transports ray across a single source region +void RandomRay::event_advance_ray() +{ + // Find the distance to the nearest boundary + boundary() = distance_to_boundary(*this); + double distance = boundary().distance; + + if (distance <= 0.0) { + mark_as_lost("Negative transport distance detected for particle " + + std::to_string(id())); + return; + } + + if (is_active_) { + // If the ray is in the active length, need to check if it has + // reached its maximum termination distance. If so, reduce + // the ray traced length so that the ray does not overrun the + // maximum numerical length (so as to avoid numerical bias). + if (distance_travelled_ + distance >= distance_active_) { + distance = distance_active_ - distance_travelled_; + wgt() = 0.0; + } + + distance_travelled_ += distance; + attenuate_flux(distance, true); + } else { + // If the ray is still in the dead zone, need to check if it + // has entered the active phase. If so, split into two segments (one + // representing the final part of the dead zone, the other representing the + // first part of the active length) and attenuate each. Otherwise, if the + // full length of the segment is within the dead zone, attenuate as normal. + if (distance_travelled_ + distance >= distance_inactive_) { + is_active_ = true; + double distance_dead = distance_inactive_ - distance_travelled_; + attenuate_flux(distance_dead, false); + + double distance_alive = distance - distance_dead; + + // Ensure we haven't travelled past the active phase as well + if (distance_alive > distance_active_) { + distance_alive = distance_active_; + wgt() = 0.0; + } + + attenuate_flux(distance_alive, true); + distance_travelled_ = distance_alive; + } else { + distance_travelled_ += distance; + attenuate_flux(distance, false); + } + } + + // Advance particle + for (int j = 0; j < n_coord(); ++j) { + coord(j).r += distance * coord(j).u; + } +} + +// This function forms the inner loop of the random ray transport process. +// It is responsible for several tasks. Based on the incoming angular flux +// of the ray and the source term in the region, the outgoing angular flux +// is computed. The delta psi between the incoming and outgoing fluxes is +// contributed to the estimate of the total scalar flux in the source region. +// Additionally, the contribution of the ray path to the stochastically +// estimated volume is also kept track of. All tasks involving writing +// to the data for the source region are done with a lock over the entire +// source region. Locks are used instead of atomics as all energy groups +// must be written, such that locking once is typically much more efficient +// than use of many atomic operations corresponding to each energy group +// individually (at least on CPU). Several other bookkeeping tasks are also +// performed when inside the lock. +void RandomRay::attenuate_flux(double distance, bool is_active) +{ + // The number of geometric intersections is counted for reporting purposes + n_event()++; + + // Determine source region index etc. + int i_cell = lowest_coord().cell; + + // The source region is the spatial region index + int64_t source_region = + domain_->source_region_offsets_[i_cell] + cell_instance(); + + // The source element is the energy-specific region index + int64_t source_element = source_region * negroups_; + int material = this->material(); + + // Temperature and angle indices, if using multiple temperature + // data sets and/or anisotropic data sets. + // TODO: Currently assumes we are only using single temp/single + // angle data. + const int t = 0; + const int a = 0; + + // MOC incoming flux attenuation + source contribution/attenuation equation + for (int g = 0; g < negroups_; g++) { + float sigma_t = data::mg.macro_xs_[material].get_xs( + MgxsType::TOTAL, g, NULL, NULL, NULL, t, a); + float tau = sigma_t * distance; + float exponential = cjosey_exponential(tau); // exponential = 1 - exp(-tau) + float new_delta_psi = + (angular_flux_[g] - domain_->source_[source_element + g]) * exponential; + delta_psi_[g] = new_delta_psi; + angular_flux_[g] -= new_delta_psi; + } + + // If ray is in the active phase (not in dead zone), make contributions to + // source region bookkeeping + if (is_active) { + + // Aquire lock for source region + domain_->lock_[source_region].lock(); + + // Accumulate delta psi into new estimate of source region flux for + // this iteration + for (int g = 0; g < negroups_; g++) { + domain_->scalar_flux_new_[source_element + g] += delta_psi_[g]; + } + + // If the source region hasn't been hit yet this iteration, + // indicate that it now has + if (domain_->was_hit_[source_region] == 0) { + domain_->was_hit_[source_region] = 1; + } + + // Accomulate volume (ray distance) into this iteration's estimate + // of the source region's volume + domain_->volume_[source_region] += distance; + + // Tally valid position inside the source region (e.g., midpoint of + // the ray) if not done already + if (!domain_->position_recorded_[source_region]) { + Position midpoint = r() + u() * (distance / 2.0); + domain_->position_[source_region] = midpoint; + domain_->position_recorded_[source_region] = 1; + } + + // Release lock + domain_->lock_[source_region].unlock(); + } +} + +void RandomRay::initialize_ray(uint64_t ray_id, FlatSourceDomain* domain) +{ + domain_ = domain; + + // Reset particle event counter + n_event() = 0; + + is_active_ = (distance_inactive_ <= 0.0); + + wgt() = 1.0; + + // set identifier for particle + id() = simulation::work_index[mpi::rank] + ray_id; + + // set random number seed + int64_t particle_seed = + (simulation::current_batch - 1) * settings::n_particles + id(); + init_particle_seeds(particle_seed, seeds()); + stream() = STREAM_TRACKING; + + // Sample from ray source distribution + SourceSite site {ray_source_->sample(current_seed())}; + site.E = lower_bound_index( + data::mg.rev_energy_bins_.begin(), data::mg.rev_energy_bins_.end(), site.E); + site.E = negroups_ - site.E - 1.; + this->from_source(&site); + + // Locate ray + if (lowest_coord().cell == C_NONE) { + if (!exhaustive_find_cell(*this)) { + this->mark_as_lost( + "Could not find the cell containing particle " + std::to_string(id())); + } + + // Set birth cell attribute + if (cell_born() == C_NONE) + cell_born() = lowest_coord().cell; + } + + // Initialize ray's starting angular flux to starting location's isotropic + // source + int i_cell = lowest_coord().cell; + int64_t source_region_idx = + domain_->source_region_offsets_[i_cell] + cell_instance(); + + for (int g = 0; g < negroups_; g++) { + angular_flux_[g] = domain_->source_[source_region_idx * negroups_ + g]; + } +} + +} // namespace openmc diff --git a/src/random_ray/random_ray_simulation.cpp b/src/random_ray/random_ray_simulation.cpp new file mode 100644 index 00000000000..b9fd93a48f6 --- /dev/null +++ b/src/random_ray/random_ray_simulation.cpp @@ -0,0 +1,397 @@ +#include "openmc/random_ray/random_ray_simulation.h" + +#include "openmc/eigenvalue.h" +#include "openmc/geometry.h" +#include "openmc/message_passing.h" +#include "openmc/mgxs_interface.h" +#include "openmc/output.h" +#include "openmc/plot.h" +#include "openmc/random_ray/random_ray.h" +#include "openmc/simulation.h" +#include "openmc/source.h" +#include "openmc/tallies/filter.h" +#include "openmc/tallies/tally.h" +#include "openmc/tallies/tally_scoring.h" +#include "openmc/timer.h" + +namespace openmc { + +//============================================================================== +// Non-member functions +//============================================================================== + +void openmc_run_random_ray() +{ + // Initialize OpenMC general data structures + openmc_simulation_init(); + + // Validate that inputs meet requirements for random ray mode + if (mpi::master) + validate_random_ray_inputs(); + + // Initialize Random Ray Simulation Object + RandomRaySimulation sim; + + // Begin main simulation timer + simulation::time_total.start(); + + // Execute random ray simulation + sim.simulate(); + + // End main simulation timer + openmc::simulation::time_total.stop(); + + // Finalize OpenMC + openmc_simulation_finalize(); + + // Reduce variables across MPI ranks + sim.reduce_simulation_statistics(); + + // Output all simulation results + sim.output_simulation_results(); +} + +// Enforces restrictions on inputs in random ray mode. While there are +// many features that don't make sense in random ray mode, and are therefore +// unsupported, we limit our testing/enforcement operations only to inputs +// that may cause erroneous/misleading output or crashes from the solver. +void validate_random_ray_inputs() +{ + // Validate tallies + /////////////////////////////////////////////////////////////////// + for (auto& tally : model::tallies) { + + // Validate score types + for (auto score_bin : tally->scores_) { + switch (score_bin) { + case SCORE_FLUX: + case SCORE_TOTAL: + case SCORE_FISSION: + case SCORE_NU_FISSION: + case SCORE_EVENTS: + break; + default: + fatal_error( + "Invalid score specified. Only flux, total, fission, nu-fission, and " + "event scores are supported in random ray mode."); + } + } + + // Validate filter types + for (auto f : tally->filters()) { + auto& filter = *model::tally_filters[f]; + + switch (filter.type()) { + case FilterType::CELL: + case FilterType::CELL_INSTANCE: + case FilterType::DISTRIBCELL: + case FilterType::ENERGY: + case FilterType::MATERIAL: + case FilterType::MESH: + case FilterType::UNIVERSE: + break; + default: + fatal_error("Invalid filter specified. Only cell, cell_instance, " + "distribcell, energy, material, mesh, and universe filters " + "are supported in random ray mode."); + } + } + } + + // Validate MGXS data + /////////////////////////////////////////////////////////////////// + for (auto& material : data::mg.macro_xs_) { + if (!material.is_isotropic) { + fatal_error("Anisotropic MGXS detected. Only isotropic XS data sets " + "supported in random ray mode."); + } + if (material.get_xsdata().size() > 1) { + fatal_error("Non-isothermal MGXS detected. Only isothermal XS data sets " + "supported in random ray mode."); + } + } + + // Validate solver mode + /////////////////////////////////////////////////////////////////// + if (settings::run_mode == RunMode::FIXED_SOURCE) { + fatal_error( + "Invalid run mode. Fixed source not yet supported in random ray mode."); + } + + // Validate ray source + /////////////////////////////////////////////////////////////////// + + // Check for independent source + IndependentSource* is = + dynamic_cast(RandomRay::ray_source_.get()); + if (!is) { + fatal_error( + "Invalid ray source definition. Ray source must be IndependentSource."); + } + + // Check for box source + SpatialDistribution* space_dist = is->space(); + SpatialBox* sb = dynamic_cast(space_dist); + if (!sb) { + fatal_error( + "Invalid source definition -- only box sources are allowed in random " + "ray " + "mode. If no source is specified, OpenMC default is an isotropic point " + "source at the origin, which is invalid in random ray mode."); + } + + // Check that box source is not restricted to fissionable areas + if (sb->only_fissionable()) { + fatal_error("Invalid source definition -- fissionable spatial distribution " + "not allowed for random ray source."); + } + + // Check for isotropic source + UnitSphereDistribution* angle_dist = is->angle(); + Isotropic* id = dynamic_cast(angle_dist); + if (!id) { + fatal_error("Invalid source definition -- only isotropic sources are " + "allowed for random ray source."); + } + + // Validate plotting files + /////////////////////////////////////////////////////////////////// + for (int p = 0; p < model::plots.size(); p++) { + + // Get handle to OpenMC plot object + Plot* openmc_plot = dynamic_cast(model::plots[p].get()); + + // Random ray plots only support voxel plots + if (!openmc_plot) { + warning(fmt::format( + "Plot {} will not be used for end of simulation data plotting -- only " + "voxel plotting is allowed in random ray mode.", + p)); + continue; + } else if (openmc_plot->type_ != Plot::PlotType::voxel) { + warning(fmt::format( + "Plot {} will not be used for end of simulation data plotting -- only " + "voxel plotting is allowed in random ray mode.", + p)); + continue; + } + } + + // Warn about slow MPI domain replication, if detected + /////////////////////////////////////////////////////////////////// +#ifdef OPENMC_MPI + if (mpi::n_procs > 1) { + warning( + "Domain replication in random ray is supported, but suffers from poor " + "scaling of source all-reduce operations. Performance may severely " + "degrade beyond just a few MPI ranks. Domain decomposition may be " + "implemented in the future to provide efficient scaling."); + } +#endif +} + +//============================================================================== +// RandomRaySimulation implementation +//============================================================================== + +RandomRaySimulation::RandomRaySimulation() + : negroups_(data::mg.num_energy_groups_) +{ + // There are no source sites in random ray mode, so be sure to disable to + // ensure we don't attempt to write source sites to statepoint + settings::source_write = false; + + // Random ray mode does not have an inner loop over generations within a + // batch, so set the current gen to 1 + simulation::current_gen = 1; +} + +void RandomRaySimulation::simulate() +{ + // Random ray power iteration loop + while (simulation::current_batch < settings::n_batches) { + + // Initialize the current batch + initialize_batch(); + initialize_generation(); + + // Reset total starting particle weight used for normalizing tallies + simulation::total_weight = 1.0; + + // Update source term (scattering + fission) + domain_.update_neutron_source(k_eff_); + + // Reset scalar fluxes, iteration volume tallies, and region hit flags to + // zero + domain_.batch_reset(); + + // Start timer for transport + simulation::time_transport.start(); + +// Transport sweep over all random rays for the iteration +#pragma omp parallel for schedule(dynamic) \ + reduction(+ : total_geometric_intersections_) + for (int i = 0; i < simulation::work_per_rank; i++) { + RandomRay ray(i, &domain_); + total_geometric_intersections_ += + ray.transport_history_based_single_ray(); + } + + simulation::time_transport.stop(); + + // If using multiple MPI ranks, perform all reduce on all transport results + domain_.all_reduce_replicated_source_regions(); + + // Normalize scalar flux and update volumes + domain_.normalize_scalar_flux_and_volumes( + settings::n_particles * RandomRay::distance_active_); + + // Add source to scalar flux, compute number of FSR hits + int64_t n_hits = domain_.add_source_to_scalar_flux(); + + // Compute random ray k-eff + k_eff_ = domain_.compute_k_eff(k_eff_); + + // Store random ray k-eff into OpenMC's native k-eff variable + global_tally_tracklength = k_eff_; + + // Execute all tallying tasks, if this is an active batch + if (simulation::current_batch > settings::n_inactive && mpi::master) { + + // Generate mapping between source regions and tallies + if (!domain_.mapped_all_tallies_) { + domain_.convert_source_regions_to_tallies(); + } + + // Use above mapping to contribute FSR flux data to appropriate tallies + domain_.random_ray_tally(); + + // Add this iteration's scalar flux estimate to final accumulated estimate + domain_.accumulate_iteration_flux(); + } + + // Set phi_old = phi_new + domain_.scalar_flux_old_.swap(domain_.scalar_flux_new_); + + // Check for any obvious insabilities/nans/infs + instability_check(n_hits, k_eff_, avg_miss_rate_); + + // Finalize the current batch + finalize_generation(); + finalize_batch(); + } // End random ray power iteration loop +} + +void RandomRaySimulation::reduce_simulation_statistics() +{ + // Reduce number of intersections +#ifdef OPENMC_MPI + if (mpi::n_procs > 1) { + uint64_t total_geometric_intersections_reduced = 0; + MPI_Reduce(&total_geometric_intersections_, + &total_geometric_intersections_reduced, 1, MPI_UNSIGNED_LONG, MPI_SUM, 0, + mpi::intracomm); + total_geometric_intersections_ = total_geometric_intersections_reduced; + } +#endif +} + +void RandomRaySimulation::output_simulation_results() const +{ + // Print random ray results + if (mpi::master) { + print_results_random_ray(total_geometric_intersections_, + avg_miss_rate_ / settings::n_batches, negroups_, + domain_.n_source_regions_); + if (model::plots.size() > 0) { + domain_.output_to_vtk(); + } + } +} + +// Apply a few sanity checks to catch obvious cases of numerical instability. +// Instability typically only occurs if ray density is extremely low. +void RandomRaySimulation::instability_check( + int64_t n_hits, double k_eff, double& avg_miss_rate) const +{ + double percent_missed = ((domain_.n_source_regions_ - n_hits) / + static_cast(domain_.n_source_regions_)) * + 100.0; + avg_miss_rate += percent_missed; + + if (percent_missed > 10.0) { + warning(fmt::format( + "Very high FSR miss rate detected ({:.3f}%). Instability may occur. " + "Increase ray density by adding more rays and/or active distance.", + percent_missed)); + } else if (percent_missed > 0.01) { + warning(fmt::format("Elevated FSR miss rate detected ({:.3f}%). Increasing " + "ray density by adding more rays and/or active " + "distance may improve simulation efficiency.", + percent_missed)); + } + + if (k_eff > 10.0 || k_eff < 0.01 || !(std::isfinite(k_eff))) { + fatal_error("Instability detected"); + } +} + +// Print random ray simulation results +void RandomRaySimulation::print_results_random_ray( + uint64_t total_geometric_intersections, double avg_miss_rate, int negroups, + int64_t n_source_regions) const +{ + using namespace simulation; + + if (settings::verbosity >= 6) { + double total_integrations = total_geometric_intersections * negroups; + double time_per_integration = + simulation::time_transport.elapsed() / total_integrations; + double misc_time = time_total.elapsed() - time_update_src.elapsed() - + time_transport.elapsed() - time_tallies.elapsed() - + time_bank_sendrecv.elapsed(); + + header("Simulation Statistics", 4); + fmt::print( + " Total Iterations = {}\n", settings::n_batches); + fmt::print(" Flat Source Regions (FSRs) = {}\n", n_source_regions); + fmt::print(" Total Geometric Intersections = {:.4e}\n", + static_cast(total_geometric_intersections)); + fmt::print(" Avg per Iteration = {:.4e}\n", + static_cast(total_geometric_intersections) / settings::n_batches); + fmt::print(" Avg per Iteration per FSR = {:.2f}\n", + static_cast(total_geometric_intersections) / + static_cast(settings::n_batches) / n_source_regions); + fmt::print(" Avg FSR Miss Rate per Iteration = {:.4f}%\n", avg_miss_rate); + fmt::print(" Energy Groups = {}\n", negroups); + fmt::print( + " Total Integrations = {:.4e}\n", total_integrations); + fmt::print(" Avg per Iteration = {:.4e}\n", + total_integrations / settings::n_batches); + + header("Timing Statistics", 4); + show_time("Total time for initialization", time_initialize.elapsed()); + show_time("Reading cross sections", time_read_xs.elapsed(), 1); + show_time("Total simulation time", time_total.elapsed()); + show_time("Transport sweep only", time_transport.elapsed(), 1); + show_time("Source update only", time_update_src.elapsed(), 1); + show_time("Tally conversion only", time_tallies.elapsed(), 1); + show_time("MPI source reductions only", time_bank_sendrecv.elapsed(), 1); + show_time("Other iteration routines", misc_time, 1); + if (settings::run_mode == RunMode::EIGENVALUE) { + show_time("Time in inactive batches", time_inactive.elapsed()); + } + show_time("Time in active batches", time_active.elapsed()); + show_time("Time writing statepoints", time_statepoint.elapsed()); + show_time("Total time for finalization", time_finalize.elapsed()); + show_time("Time per integration", time_per_integration); + } + + if (settings::verbosity >= 4) { + header("Results", 4); + fmt::print(" k-effective = {:.5f} +/- {:.5f}\n", + simulation::keff, simulation::keff_std); + } +} + +} // namespace openmc diff --git a/src/settings.cpp b/src/settings.cpp index 9f183a6c167..6790f2cc0f7 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -24,6 +24,7 @@ #include "openmc/output.h" #include "openmc/plot.h" #include "openmc/random_lcg.h" +#include "openmc/random_ray/random_ray.h" #include "openmc/simulation.h" #include "openmc/source.h" #include "openmc/string_utils.h" @@ -113,6 +114,7 @@ double res_scat_energy_min {0.01}; double res_scat_energy_max {1000.0}; vector res_scat_nuclides; RunMode run_mode {RunMode::UNSET}; +SolverType solver_type {SolverType::MONTE_CARLO}; std::unordered_set sourcepoint_batch; std::unordered_set statepoint_batch; std::unordered_set source_write_surf_id; @@ -233,6 +235,38 @@ void get_run_parameters(pugi::xml_node node_base) } } } + + // Random ray variables + if (solver_type == SolverType::RANDOM_RAY) { + xml_node random_ray_node = node_base.child("random_ray"); + if (check_for_node(random_ray_node, "distance_active")) { + RandomRay::distance_active_ = + std::stod(get_node_value(random_ray_node, "distance_active")); + if (RandomRay::distance_active_ <= 0.0) { + fatal_error("Random ray active distance must be greater than 0"); + } + } else { + fatal_error("Specify random ray active distance in settings XML"); + } + if (check_for_node(random_ray_node, "distance_inactive")) { + RandomRay::distance_inactive_ = + std::stod(get_node_value(random_ray_node, "distance_inactive")); + if (RandomRay::distance_inactive_ < 0) { + fatal_error( + "Random ray inactive distance must be greater than or equal to 0"); + } + } else { + fatal_error("Specify random ray inactive distance in settings XML"); + } + if (check_for_node(random_ray_node, "source")) { + xml_node source_node = random_ray_node.child("source"); + // Get point to list of elements and make sure there is at least + // one + RandomRay::ray_source_ = Source::create(source_node); + } else { + fatal_error("Specify random ray source in settings XML"); + } + } } void read_settings_xml() @@ -389,6 +423,14 @@ void read_settings_xml(pugi::xml_node root) } } + // Check solver type + if (check_for_node(root, "random_ray")) { + solver_type = SolverType::RANDOM_RAY; + if (run_CE) + fatal_error("multi-group energy mode must be specified in settings XML " + "when using the random ray solver."); + } + if (run_mode == RunMode::EIGENVALUE || run_mode == RunMode::FIXED_SOURCE) { // Read run parameters get_run_parameters(node_mode); diff --git a/src/simulation.cpp b/src/simulation.cpp index a7aea69424d..1cf34a820db 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -122,7 +122,8 @@ int openmc_simulation_init() write_message("Resuming simulation...", 6); } else { // Only initialize primary source bank for eigenvalue simulations - if (settings::run_mode == RunMode::EIGENVALUE) { + if (settings::run_mode == RunMode::EIGENVALUE && + settings::solver_type == SolverType::MONTE_CARLO) { initialize_source(); } } @@ -132,7 +133,11 @@ int openmc_simulation_init() if (settings::run_mode == RunMode::FIXED_SOURCE) { header("FIXED SOURCE TRANSPORT SIMULATION", 3); } else if (settings::run_mode == RunMode::EIGENVALUE) { - header("K EIGENVALUE SIMULATION", 3); + if (settings::solver_type == SolverType::MONTE_CARLO) { + header("K EIGENVALUE SIMULATION", 3); + } else if (settings::solver_type == SolverType::RANDOM_RAY) { + header("K EIGENVALUE SIMULATION (RANDOM RAY SOLVER)", 3); + } if (settings::verbosity >= 7) print_columns(); } @@ -196,10 +201,12 @@ int openmc_simulation_finalize() simulation::time_finalize.stop(); simulation::time_total.stop(); if (mpi::master) { - if (settings::verbosity >= 6) - print_runtime(); - if (settings::verbosity >= 4) - print_results(); + if (settings::solver_type != SolverType::RANDOM_RAY) { + if (settings::verbosity >= 6) + print_runtime(); + if (settings::verbosity >= 4) + print_results(); + } } if (settings::check_overlaps) print_overlap_check(); @@ -309,7 +316,8 @@ vector work_index; void allocate_banks() { - if (settings::run_mode == RunMode::EIGENVALUE) { + if (settings::run_mode == RunMode::EIGENVALUE && + settings::solver_type == SolverType::MONTE_CARLO) { // Allocate source bank simulation::source_bank.resize(simulation::work_per_rank); @@ -493,7 +501,8 @@ void finalize_generation() } global_tally_leakage = 0.0; - if (settings::run_mode == RunMode::EIGENVALUE) { + if (settings::run_mode == RunMode::EIGENVALUE && + settings::solver_type == SolverType::MONTE_CARLO) { // If using shared memory, stable sort the fission bank (by parent IDs) // so as to allow for reproducibility regardless of which order particles // are run in. @@ -501,6 +510,9 @@ void finalize_generation() // Distribute fission bank across processors evenly synchronize_bank(); + } + + if (settings::run_mode == RunMode::EIGENVALUE) { // Calculate shannon entropy if (settings::entropy_on) diff --git a/src/source.cpp b/src/source.cpp index 778962667bb..5ddac7f4287 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -243,36 +243,40 @@ SourceSite IndependentSource::sample(uint64_t* seed) const // Sample angle site.u = angle_->sample(seed); - // Check for monoenergetic source above maximum particle energy - auto p = static_cast(particle_); - auto energy_ptr = dynamic_cast(energy_.get()); - if (energy_ptr) { - auto energies = xt::adapt(energy_ptr->x()); - if (xt::any(energies > data::energy_max[p])) { - fatal_error("Source energy above range of energies of at least " - "one cross section table"); + // Sample energy and time for neutron and photon sources + if (settings::solver_type != SolverType::RANDOM_RAY) { + // Check for monoenergetic source above maximum particle energy + auto p = static_cast(particle_); + auto energy_ptr = dynamic_cast(energy_.get()); + if (energy_ptr) { + auto energies = xt::adapt(energy_ptr->x()); + if (xt::any(energies > data::energy_max[p])) { + fatal_error("Source energy above range of energies of at least " + "one cross section table"); + } } - } - while (true) { - // Sample energy spectrum - site.E = energy_->sample(seed); + while (true) { + // Sample energy spectrum + site.E = energy_->sample(seed); - // Resample if energy falls above maximum particle energy - if (site.E < data::energy_max[p]) - break; + // Resample if energy falls above maximum particle energy + if (site.E < data::energy_max[p]) + break; - n_reject++; - if (n_reject >= EXTSRC_REJECT_THRESHOLD && - static_cast(n_accept) / n_reject <= EXTSRC_REJECT_FRACTION) { - fatal_error("More than 95% of external source sites sampled were " - "rejected. Please check your external source energy spectrum " - "definition."); + n_reject++; + if (n_reject >= EXTSRC_REJECT_THRESHOLD && + static_cast(n_accept) / n_reject <= EXTSRC_REJECT_FRACTION) { + fatal_error( + "More than 95% of external source sites sampled were " + "rejected. Please check your external source energy spectrum " + "definition."); + } } - } - // Sample particle creation time - site.time = time_->sample(seed); + // Sample particle creation time + site.time = time_->sample(seed); + } // Increment number of accepted samples ++n_accept; diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index df1ec5ea797..2e77bcad25f 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -757,6 +757,10 @@ void Tally::accumulate() double norm = total_source / (settings::n_particles * settings::gen_per_batch); + if (settings::solver_type == SolverType::RANDOM_RAY) { + norm = 1.0; + } + // Accumulate each result #pragma omp parallel for for (int i = 0; i < results_.shape()[0]; ++i) { @@ -953,8 +957,9 @@ void accumulate_tallies() { #ifdef OPENMC_MPI // Combine tally results onto master process - if (mpi::n_procs > 1) + if (mpi::n_procs > 1 && settings::solver_type == SolverType::MONTE_CARLO) { reduce_tally_results(); + } #endif // Increase number of realizations (only used for global tallies) diff --git a/src/timer.cpp b/src/timer.cpp index 86436758a3f..6d692d4fbf6 100644 --- a/src/timer.cpp +++ b/src/timer.cpp @@ -26,6 +26,7 @@ Timer time_event_advance_particle; Timer time_event_surface_crossing; Timer time_event_collision; Timer time_event_death; +Timer time_update_src; } // namespace simulation @@ -85,6 +86,7 @@ void reset_timers() simulation::time_event_surface_crossing.reset(); simulation::time_event_collision.reset(); simulation::time_event_death.reset(); + simulation::time_update_src.reset(); } } // namespace openmc diff --git a/tests/regression_tests/random_ray_basic/__init__.py b/tests/regression_tests/random_ray_basic/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/regression_tests/random_ray_basic/inputs_true.dat b/tests/regression_tests/random_ray_basic/inputs_true.dat new file mode 100644 index 00000000000..97b7906f7b2 --- /dev/null +++ b/tests/regression_tests/random_ray_basic/inputs_true.dat @@ -0,0 +1,108 @@ + + + + mgxs.h5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.126 0.126 + 10 10 + -0.63 -0.63 + +3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 + + + 1.26 1.26 + 2 2 + -1.26 -1.26 + +2 2 +2 5 + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + multi-group + + 100.0 + 20.0 + + + -1.26 -1.26 -1 1.26 1.26 1 + + + + + + + 2 2 + -1.26 -1.26 + 1.26 1.26 + + + 1 + + + 1e-05 0.0635 10.0 100.0 1000.0 500000.0 1000000.0 20000000.0 + + + 1 2 + flux fission nu-fission + analog + + + diff --git a/tests/regression_tests/random_ray_basic/results_true.dat b/tests/regression_tests/random_ray_basic/results_true.dat new file mode 100644 index 00000000000..802e78a828b --- /dev/null +++ b/tests/regression_tests/random_ray_basic/results_true.dat @@ -0,0 +1,171 @@ +k-combined: +8.400322E-01 8.023349E-03 +tally 1: +1.260220E+00 +3.179889E-01 +1.484289E-01 +4.411066E-03 +3.612463E-01 +2.612843E-02 +7.086707E-01 +1.006119E-01 +3.342483E-02 +2.238499E-04 +8.134936E-02 +1.325949E-03 +4.194328E-01 +3.558669E-02 +4.287776E-03 +3.717447E-06 +1.043559E-02 +2.201986E-05 +5.878720E-01 +7.045887E-02 +6.147757E-03 +7.701173E-06 +1.496241E-02 +4.561699E-05 +1.768113E+00 +6.356917E-01 +6.513486E-03 +8.628535E-06 +1.585272E-02 +5.111136E-05 +5.063704E+00 +5.152401E+00 +2.440293E-03 +1.196869E-06 +6.038334E-03 +7.328193E-06 +3.253717E+00 +2.117655E+00 +1.389120E-02 +3.859385E-05 +3.863767E-02 +2.985798E-04 +1.876994E+00 +7.046366E-01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +8.390875E-01 +1.408791E-01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.513839E-01 +4.139640E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.682186E-01 +9.116003E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.849034E+00 +6.944337E-01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.523425E+00 +4.112118E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.821432E+00 +1.592568E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.159618E+00 +2.694138E-01 +1.354028E-01 +3.672094E-03 +3.295432E-01 +2.175122E-02 +6.880334E-01 +9.491215E-02 +3.234611E-02 +2.097782E-04 +7.872396E-02 +1.242596E-03 +4.184841E-01 +3.536436E-02 +4.274305E-03 +3.687209E-06 +1.040280E-02 +2.184074E-05 +5.810180E-01 +6.872944E-02 +6.060273E-03 +7.476500E-06 +1.474949E-02 +4.428617E-05 +1.782580E+00 +6.457892E-01 +6.552384E-03 +8.730345E-06 +1.594739E-02 +5.171444E-05 +5.278155E+00 +5.596601E+00 +2.546878E-03 +1.303010E-06 +6.302072E-03 +7.978072E-06 +3.420419E+00 +2.340454E+00 +1.465798E-02 +4.299061E-05 +4.077042E-02 +3.325951E-04 +1.279417E+00 +3.278133E-01 +1.509073E-01 +4.561836E-03 +3.672782E-01 +2.702150E-02 +7.212777E-01 +1.042487E-01 +3.411552E-02 +2.332877E-04 +8.303035E-02 +1.381852E-03 +4.269473E-01 +3.685202E-02 +4.378540E-03 +3.872997E-06 +1.065649E-02 +2.294124E-05 +5.973530E-01 +7.266946E-02 +6.260881E-03 +7.976490E-06 +1.523773E-02 +4.724780E-05 +1.795373E+00 +6.547440E-01 +6.635941E-03 +8.945067E-06 +1.615075E-02 +5.298634E-05 +5.161876E+00 +5.353441E+00 +2.505311E-03 +1.261399E-06 +6.199218E-03 +7.723296E-06 +3.344042E+00 +2.236603E+00 +1.443089E-02 +4.166228E-05 +4.013879E-02 +3.223186E-04 diff --git a/tests/regression_tests/random_ray_basic/test.py b/tests/regression_tests/random_ray_basic/test.py new file mode 100644 index 00000000000..1727a63716c --- /dev/null +++ b/tests/regression_tests/random_ray_basic/test.py @@ -0,0 +1,232 @@ +import os + +import numpy as np +import openmc + +from tests.testing_harness import TolerantPyAPITestHarness + + +class MGXSTestHarness(TolerantPyAPITestHarness): + def _cleanup(self): + super()._cleanup() + f = 'mgxs.h5' + if os.path.exists(f): + os.remove(f) + + +def random_ray_model() -> openmc.Model: + ############################################################################### + # Create multigroup data + + # Instantiate the energy group data + group_edges = [1e-5, 0.0635, 10.0, 1.0e2, 1.0e3, 0.5e6, 1.0e6, 20.0e6] + groups = openmc.mgxs.EnergyGroups(group_edges) + + # Instantiate the 7-group (C5G7) cross section data + uo2_xsdata = openmc.XSdata('UO2', groups) + uo2_xsdata.order = 0 + uo2_xsdata.set_total( + [0.1779492, 0.3298048, 0.4803882, 0.5543674, 0.3118013, 0.3951678, + 0.5644058]) + uo2_xsdata.set_absorption([8.0248e-03, 3.7174e-03, 2.6769e-02, 9.6236e-02, + 3.0020e-02, 1.1126e-01, 2.8278e-01]) + scatter_matrix = np.array( + [[[0.1275370, 0.0423780, 0.0000094, 0.0000000, 0.0000000, 0.0000000, 0.0000000], + [0.0000000, 0.3244560, 0.0016314, 0.0000000, 0.0000000, 0.0000000, 0.0000000], + [0.0000000, 0.0000000, 0.4509400, 0.0026792, 0.0000000, 0.0000000, 0.0000000], + [0.0000000, 0.0000000, 0.0000000, 0.4525650, 0.0055664, 0.0000000, 0.0000000], + [0.0000000, 0.0000000, 0.0000000, 0.0001253, 0.2714010, 0.0102550, 0.0000000], + [0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0012968, 0.2658020, 0.0168090], + [0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0085458, 0.2730800]]]) + scatter_matrix = np.rollaxis(scatter_matrix, 0, 3) + uo2_xsdata.set_scatter_matrix(scatter_matrix) + uo2_xsdata.set_fission([7.21206e-03, 8.19301e-04, 6.45320e-03, + 1.85648e-02, 1.78084e-02, 8.30348e-02, + 2.16004e-01]) + uo2_xsdata.set_nu_fission([2.005998e-02, 2.027303e-03, 1.570599e-02, + 4.518301e-02, 4.334208e-02, 2.020901e-01, + 5.257105e-01]) + uo2_xsdata.set_chi([5.8791e-01, 4.1176e-01, 3.3906e-04, 1.1761e-07, 0.0000e+00, + 0.0000e+00, 0.0000e+00]) + + h2o_xsdata = openmc.XSdata('LWTR', groups) + h2o_xsdata.order = 0 + h2o_xsdata.set_total([0.15920605, 0.412969593, 0.59030986, 0.58435, + 0.718, 1.2544497, 2.650379]) + h2o_xsdata.set_absorption([6.0105e-04, 1.5793e-05, 3.3716e-04, + 1.9406e-03, 5.7416e-03, 1.5001e-02, + 3.7239e-02]) + scatter_matrix = np.array( + [[[0.0444777, 0.1134000, 0.0007235, 0.0000037, 0.0000001, 0.0000000, 0.0000000], + [0.0000000, 0.2823340, 0.1299400, 0.0006234, 0.0000480, 0.0000074, 0.0000010], + [0.0000000, 0.0000000, 0.3452560, 0.2245700, 0.0169990, 0.0026443, 0.0005034], + [0.0000000, 0.0000000, 0.0000000, 0.0910284, 0.4155100, 0.0637320, 0.0121390], + [0.0000000, 0.0000000, 0.0000000, 0.0000714, 0.1391380, 0.5118200, 0.0612290], + [0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0022157, 0.6999130, 0.5373200], + [0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.1324400, 2.4807000]]]) + scatter_matrix = np.rollaxis(scatter_matrix, 0, 3) + h2o_xsdata.set_scatter_matrix(scatter_matrix) + + mg_cross_sections = openmc.MGXSLibrary(groups) + mg_cross_sections.add_xsdatas([uo2_xsdata, h2o_xsdata]) + mg_cross_sections.export_to_hdf5() + + ############################################################################### + # Create materials for the problem + + # Instantiate some Materials and register the appropriate macroscopic data + uo2 = openmc.Material(name='UO2 fuel') + uo2.set_density('macro', 1.0) + uo2.add_macroscopic('UO2') + + water = openmc.Material(name='Water') + water.set_density('macro', 1.0) + water.add_macroscopic('LWTR') + + # Instantiate a Materials collection and export to XML + materials = openmc.Materials([uo2, water]) + materials.cross_sections = "mgxs.h5" + + ############################################################################### + # Define problem geometry + + ######################################## + # Define an unbounded pincell universe + + pitch = 1.26 + + # Create a surface for the fuel outer radius + fuel_or = openmc.ZCylinder(r=0.54, name='Fuel OR') + inner_ring_a = openmc.ZCylinder(r=0.33, name='inner ring a') + inner_ring_b = openmc.ZCylinder(r=0.45, name='inner ring b') + outer_ring_a = openmc.ZCylinder(r=0.60, name='outer ring a') + outer_ring_b = openmc.ZCylinder(r=0.69, name='outer ring b') + + # Instantiate Cells + fuel_a = openmc.Cell(fill=uo2, region=-inner_ring_a, name='fuel inner a') + fuel_b = openmc.Cell(fill=uo2, region=+inner_ring_a & -inner_ring_b, name='fuel inner b') + fuel_c = openmc.Cell(fill=uo2, region=+inner_ring_b & -fuel_or, name='fuel inner c') + moderator_a = openmc.Cell(fill=water, region=+fuel_or & -outer_ring_a, name='moderator inner a') + moderator_b = openmc.Cell(fill=water, region=+outer_ring_a & -outer_ring_b, name='moderator outer b') + moderator_c = openmc.Cell(fill=water, region=+outer_ring_b, name='moderator outer c') + + # Create pincell universe + pincell_base = openmc.Universe() + + # Register Cells with Universe + pincell_base.add_cells([fuel_a, fuel_b, fuel_c, moderator_a, moderator_b, moderator_c]) + + # Create planes for azimuthal sectors + azimuthal_planes = [] + for i in range(8): + angle = 2 * i * openmc.pi / 8 + normal_vector = (-openmc.sin(angle), openmc.cos(angle), 0) + azimuthal_planes.append(openmc.Plane(a=normal_vector[0], b=normal_vector[1], c=normal_vector[2], d=0)) + + # Create a cell for each azimuthal sector + azimuthal_cells = [] + for i in range(8): + azimuthal_cell = openmc.Cell(name=f'azimuthal_cell_{i}') + azimuthal_cell.fill = pincell_base + azimuthal_cell.region = +azimuthal_planes[i] & -azimuthal_planes[(i+1) % 8] + azimuthal_cells.append(azimuthal_cell) + + # Create a geometry with the azimuthal universes + pincell = openmc.Universe(cells=azimuthal_cells) + + ######################################## + # Define a moderator lattice universe + + moderator_infinite = openmc.Cell(fill=water, name='moderator infinite') + mu = openmc.Universe() + mu.add_cells([moderator_infinite]) + + lattice = openmc.RectLattice() + lattice.lower_left = [-pitch/2.0, -pitch/2.0] + lattice.pitch = [pitch/10.0, pitch/10.0] + lattice.universes = np.full((10, 10), mu) + + mod_lattice_cell = openmc.Cell(fill=lattice) + + mod_lattice_uni = openmc.Universe() + + mod_lattice_uni.add_cells([mod_lattice_cell]) + + ######################################## + # Define 2x2 outer lattice + lattice2x2 = openmc.RectLattice() + lattice2x2.lower_left = (-pitch, -pitch) + lattice2x2.pitch = (pitch, pitch) + lattice2x2.universes = [ + [pincell, pincell], + [pincell, mod_lattice_uni] + ] + + ######################################## + # Define cell containing lattice and other stuff + box = openmc.model.RectangularPrism(pitch*2, pitch*2, boundary_type='reflective') + + assembly = openmc.Cell(fill=lattice2x2, region=-box, name='assembly') + + # Create a geometry with the top-level cell + geometry = openmc.Geometry([assembly]) + + ############################################################################### + # Define problem settings + + # Instantiate a Settings object, set all runtime parameters, and export to XML + settings = openmc.Settings() + settings.energy_mode = "multi-group" + settings.batches = 10 + settings.inactive = 5 + settings.particles = 100 + + # Create an initial uniform spatial source distribution over fissionable zones + lower_left = (-pitch, -pitch, -1) + upper_right = (pitch, pitch, 1) + uniform_dist = openmc.stats.Box(lower_left, upper_right) + rr_source = openmc.IndependentSource(space=uniform_dist) + + settings.random_ray['distance_active'] = 100.0 + settings.random_ray['distance_inactive'] = 20.0 + settings.random_ray['ray_source'] = rr_source + + ############################################################################### + # Define tallies + + # Create a mesh that will be used for tallying + mesh = openmc.RegularMesh() + mesh.dimension = (2, 2) + mesh.lower_left = (-pitch, -pitch) + mesh.upper_right = (pitch, pitch) + + # Create a mesh filter that can be used in a tally + mesh_filter = openmc.MeshFilter(mesh) + + # Create an energy group filter as well + energy_filter = openmc.EnergyFilter(group_edges) + + # Now use the mesh filter in a tally and indicate what scores are desired + tally = openmc.Tally(name="Mesh tally") + tally.filters = [mesh_filter, energy_filter] + tally.scores = ['flux', 'fission', 'nu-fission'] + tally.estimator = 'analog' + + # Instantiate a Tallies collection and export to XML + tallies = openmc.Tallies([tally]) + + ############################################################################### + # Exporting to OpenMC model + ############################################################################### + + model = openmc.Model() + model.geometry = geometry + model.materials = materials + model.settings = settings + model.tallies = tallies + return model + + +def test_random_ray_basic(): + harness = MGXSTestHarness('statepoint.10.h5', random_ray_model()) + harness.main() diff --git a/tests/regression_tests/random_ray_vacuum/__init__.py b/tests/regression_tests/random_ray_vacuum/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/regression_tests/random_ray_vacuum/inputs_true.dat b/tests/regression_tests/random_ray_vacuum/inputs_true.dat new file mode 100644 index 00000000000..4ef10942005 --- /dev/null +++ b/tests/regression_tests/random_ray_vacuum/inputs_true.dat @@ -0,0 +1,108 @@ + + + + mgxs.h5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.126 0.126 + 10 10 + -0.63 -0.63 + +3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 + + + 1.26 1.26 + 2 2 + -1.26 -1.26 + +2 2 +2 5 + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + multi-group + + 100.0 + 20.0 + + + -1.26 -1.26 -1 1.26 1.26 1 + + + + + + + 2 2 + -1.26 -1.26 + 1.26 1.26 + + + 1 + + + 1e-05 0.0635 10.0 100.0 1000.0 500000.0 1000000.0 20000000.0 + + + 1 2 + flux fission nu-fission + analog + + + diff --git a/tests/regression_tests/random_ray_vacuum/results_true.dat b/tests/regression_tests/random_ray_vacuum/results_true.dat new file mode 100644 index 00000000000..744ce6cef28 --- /dev/null +++ b/tests/regression_tests/random_ray_vacuum/results_true.dat @@ -0,0 +1,171 @@ +k-combined: +1.010455E-01 1.585558E-02 +tally 1: +1.849176E-01 +7.634332E-03 +2.181815E-02 +1.062861E-04 +5.310100E-02 +6.295730E-04 +4.048251E-02 +3.851890E-04 +1.893676E-03 +8.448769E-07 +4.608828E-03 +5.004529E-06 +4.063643E-03 +4.022442E-06 +4.112970E-05 +4.186661E-10 +1.001015E-04 +2.479919E-09 +7.467029E-03 +1.178864E-05 +7.688748E-05 +1.266903E-09 +1.871288E-04 +7.504350E-09 +3.870644E-02 +3.010745E-04 +1.375240E-04 +3.807356E-09 +3.347099E-04 +2.255298E-08 +4.524967E-01 +4.098857E-02 +2.437418E-04 +1.190325E-08 +6.031220E-04 +7.288126E-08 +4.989226E-01 +4.993728E-02 +2.374296E-03 +1.135824E-06 +6.603983E-03 +8.787258E-06 +3.899991E-01 +3.308783E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +7.108982E-02 +1.144390E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.295259E-03 +6.352159E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.852001E-03 +1.984406E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.414391E-02 +3.905201E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.571668E-01 +1.323140E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.752932E-01 +1.517930E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.465446E-01 +4.901884E-03 +1.700791E-02 +6.587674E-05 +4.139385E-02 +3.902131E-04 +3.424032E-02 +2.841338E-04 +1.598985E-03 +6.216312E-07 +3.891610E-03 +3.682159E-06 +4.067582E-03 +4.209468E-06 +4.152829E-05 +4.494649E-10 +1.010715E-04 +2.662352E-09 +7.526712E-03 +1.225032E-05 +7.769969E-05 +1.328443E-09 +1.891055E-04 +7.868877E-09 +4.008649E-02 +3.246821E-04 +1.417944E-04 +4.070719E-09 +3.451035E-04 +2.411301E-08 +4.859902E-01 +4.747592E-02 +2.606214E-04 +1.369749E-08 +6.448895E-04 +8.386705E-08 +5.475198E-01 +6.061269E-02 +2.625477E-03 +1.405458E-06 +7.302631E-03 +1.087327E-05 +1.909660E-01 +8.147906E-03 +2.269063E-02 +1.149570E-04 +5.522446E-02 +6.809342E-04 +4.196583E-02 +4.141620E-04 +1.980406E-03 +9.227119E-07 +4.819913E-03 +5.465576E-06 +4.247004E-03 +4.420116E-06 +4.341806E-05 +4.691518E-10 +1.056709E-04 +2.778965E-09 +7.742814E-03 +1.272112E-05 +8.039606E-05 +1.389209E-09 +1.956679E-04 +8.228817E-09 +3.982370E-02 +3.190931E-04 +1.427171E-04 +4.103942E-09 +3.473492E-04 +2.430981E-08 +4.849535E-01 +4.707014E-02 +2.678327E-04 +1.438540E-08 +6.627333E-04 +8.807897E-08 +5.493457E-01 +6.069440E-02 +2.717400E-03 +1.501450E-06 +7.558312E-03 +1.161591E-05 diff --git a/tests/regression_tests/random_ray_vacuum/test.py b/tests/regression_tests/random_ray_vacuum/test.py new file mode 100644 index 00000000000..e9ca2252144 --- /dev/null +++ b/tests/regression_tests/random_ray_vacuum/test.py @@ -0,0 +1,235 @@ +import os + +import numpy as np +import openmc + +from tests.testing_harness import TolerantPyAPITestHarness + + +class MGXSTestHarness(TolerantPyAPITestHarness): + def _cleanup(self): + super()._cleanup() + f = 'mgxs.h5' + if os.path.exists(f): + os.remove(f) + + +def random_ray_model() -> openmc.Model: + ############################################################################### + # Create multigroup data + + # Instantiate the energy group data + group_edges = [1e-5, 0.0635, 10.0, 1.0e2, 1.0e3, 0.5e6, 1.0e6, 20.0e6] + groups = openmc.mgxs.EnergyGroups(group_edges) + + # Instantiate the 7-group (C5G7) cross section data + uo2_xsdata = openmc.XSdata('UO2', groups) + uo2_xsdata.order = 0 + uo2_xsdata.set_total( + [0.1779492, 0.3298048, 0.4803882, 0.5543674, 0.3118013, 0.3951678, + 0.5644058]) + uo2_xsdata.set_absorption([8.0248e-03, 3.7174e-03, 2.6769e-02, 9.6236e-02, + 3.0020e-02, 1.1126e-01, 2.8278e-01]) + scatter_matrix = np.array( + [[[0.1275370, 0.0423780, 0.0000094, 0.0000000, 0.0000000, 0.0000000, 0.0000000], + [0.0000000, 0.3244560, 0.0016314, 0.0000000, 0.0000000, 0.0000000, 0.0000000], + [0.0000000, 0.0000000, 0.4509400, 0.0026792, 0.0000000, 0.0000000, 0.0000000], + [0.0000000, 0.0000000, 0.0000000, 0.4525650, 0.0055664, 0.0000000, 0.0000000], + [0.0000000, 0.0000000, 0.0000000, 0.0001253, 0.2714010, 0.0102550, 0.0000000], + [0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0012968, 0.2658020, 0.0168090], + [0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0085458, 0.2730800]]]) + scatter_matrix = np.rollaxis(scatter_matrix, 0, 3) + uo2_xsdata.set_scatter_matrix(scatter_matrix) + uo2_xsdata.set_fission([7.21206e-03, 8.19301e-04, 6.45320e-03, + 1.85648e-02, 1.78084e-02, 8.30348e-02, + 2.16004e-01]) + uo2_xsdata.set_nu_fission([2.005998e-02, 2.027303e-03, 1.570599e-02, + 4.518301e-02, 4.334208e-02, 2.020901e-01, + 5.257105e-01]) + uo2_xsdata.set_chi([5.8791e-01, 4.1176e-01, 3.3906e-04, 1.1761e-07, 0.0000e+00, + 0.0000e+00, 0.0000e+00]) + + h2o_xsdata = openmc.XSdata('LWTR', groups) + h2o_xsdata.order = 0 + h2o_xsdata.set_total([0.15920605, 0.412969593, 0.59030986, 0.58435, + 0.718, 1.2544497, 2.650379]) + h2o_xsdata.set_absorption([6.0105e-04, 1.5793e-05, 3.3716e-04, + 1.9406e-03, 5.7416e-03, 1.5001e-02, + 3.7239e-02]) + scatter_matrix = np.array( + [[[0.0444777, 0.1134000, 0.0007235, 0.0000037, 0.0000001, 0.0000000, 0.0000000], + [0.0000000, 0.2823340, 0.1299400, 0.0006234, 0.0000480, 0.0000074, 0.0000010], + [0.0000000, 0.0000000, 0.3452560, 0.2245700, 0.0169990, 0.0026443, 0.0005034], + [0.0000000, 0.0000000, 0.0000000, 0.0910284, 0.4155100, 0.0637320, 0.0121390], + [0.0000000, 0.0000000, 0.0000000, 0.0000714, 0.1391380, 0.5118200, 0.0612290], + [0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0022157, 0.6999130, 0.5373200], + [0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.1324400, 2.4807000]]]) + scatter_matrix = np.rollaxis(scatter_matrix, 0, 3) + h2o_xsdata.set_scatter_matrix(scatter_matrix) + + mg_cross_sections = openmc.MGXSLibrary(groups) + mg_cross_sections.add_xsdatas([uo2_xsdata, h2o_xsdata]) + mg_cross_sections.export_to_hdf5() + + ############################################################################### + # Create materials for the problem + + # Instantiate some Materials and register the appropriate Macroscopic objects + uo2 = openmc.Material(name='UO2 fuel') + uo2.set_density('macro', 1.0) + uo2.add_macroscopic('UO2') + + water = openmc.Material(name='Water') + water.set_density('macro', 1.0) + water.add_macroscopic('LWTR') + + # Instantiate a Materials collection and export to XML + materials = openmc.Materials([uo2, water]) + materials.cross_sections = "mgxs.h5" + + ############################################################################### + # Define problem geometry + + ######################################## + # Define an unbounded pincell universe + + pitch = 1.26 + + # Create a surface for the fuel outer radius + fuel_or = openmc.ZCylinder(r=0.54, name='Fuel OR') + inner_ring_a = openmc.ZCylinder(r=0.33, name='inner ring a') + inner_ring_b = openmc.ZCylinder(r=0.45, name='inner ring b') + outer_ring_a = openmc.ZCylinder(r=0.60, name='outer ring a') + outer_ring_b = openmc.ZCylinder(r=0.69, name='outer ring b') + + # Instantiate Cells + fuel_a = openmc.Cell(fill=uo2, region=-inner_ring_a, name='fuel inner a') + fuel_b = openmc.Cell(fill=uo2, region=+inner_ring_a & -inner_ring_b, name='fuel inner b') + fuel_c = openmc.Cell(fill=uo2, region=+inner_ring_b & -fuel_or, name='fuel inner c') + moderator_a = openmc.Cell(fill=water, region=+fuel_or & -outer_ring_a, name='moderator inner a') + moderator_b = openmc.Cell(fill=water, region=+outer_ring_a & -outer_ring_b, name='moderator outer b') + moderator_c = openmc.Cell(fill=water, region=+outer_ring_b, name='moderator outer c') + + # Create pincell universe + pincell_base = openmc.Universe() + + # Register Cells with Universe + pincell_base.add_cells([fuel_a, fuel_b, fuel_c, moderator_a, moderator_b, moderator_c]) + + # Create planes for azimuthal sectors + azimuthal_planes = [] + for i in range(8): + angle = 2 * i * openmc.pi / 8 + normal_vector = (-openmc.sin(angle), openmc.cos(angle), 0) + azimuthal_planes.append(openmc.Plane(a=normal_vector[0], b=normal_vector[1], c=normal_vector[2], d=0)) + + # Create a cell for each azimuthal sector + azimuthal_cells = [] + for i in range(8): + azimuthal_cell = openmc.Cell(name=f'azimuthal_cell_{i}') + azimuthal_cell.fill = pincell_base + azimuthal_cell.region = +azimuthal_planes[i] & -azimuthal_planes[(i+1) % 8] + azimuthal_cells.append(azimuthal_cell) + + # Create a geometry with the azimuthal universes + pincell = openmc.Universe(cells=azimuthal_cells) + + ######################################## + # Define a moderator lattice universe + + moderator_infinite = openmc.Cell(fill=water, name='moderator infinite') + mu = openmc.Universe() + mu.add_cells([moderator_infinite]) + + lattice = openmc.RectLattice() + lattice.lower_left = [-pitch/2.0, -pitch/2.0] + lattice.pitch = [pitch/10.0, pitch/10.0] + lattice.universes = np.full((10, 10), mu) + + mod_lattice_cell = openmc.Cell(fill=lattice) + + mod_lattice_uni = openmc.Universe() + + mod_lattice_uni.add_cells([mod_lattice_cell]) + + ######################################## + # Define 2x2 outer lattice + lattice2x2 = openmc.RectLattice() + lattice2x2.lower_left = [-pitch, -pitch] + lattice2x2.pitch = [pitch, pitch] + lattice2x2.universes = [ + [pincell, pincell], + [pincell, mod_lattice_uni] + ] + + ######################################## + # Define cell containing lattice and other stuff + box = openmc.model.RectangularPrism(pitch*2, pitch*2, boundary_type='vacuum') + + assembly = openmc.Cell(fill=lattice2x2, region=-box, name='assembly') + + root = openmc.Universe(name='root universe') + root.add_cell(assembly) + + # Create a geometry with the two cells and export to XML + geometry = openmc.Geometry(root) + + ############################################################################### + # Define problem settings + + # Instantiate a Settings object, set all runtime parameters, and export to XML + settings = openmc.Settings() + settings.energy_mode = "multi-group" + settings.batches = 10 + settings.inactive = 5 + settings.particles = 100 + + # Create an initial uniform spatial source distribution over fissionable zones + lower_left = (-pitch, -pitch, -1) + upper_right = (pitch, pitch, 1) + uniform_dist = openmc.stats.Box(lower_left, upper_right) + rr_source = openmc.IndependentSource(space=uniform_dist) + + settings.random_ray['distance_active'] = 100.0 + settings.random_ray['distance_inactive'] = 20.0 + settings.random_ray['ray_source'] = rr_source + + ############################################################################### + # Define tallies + + # Create a mesh that will be used for tallying + mesh = openmc.RegularMesh() + mesh.dimension = (2, 2) + mesh.lower_left = (-pitch, -pitch) + mesh.upper_right = (pitch, pitch) + + # Create a mesh filter that can be used in a tally + mesh_filter = openmc.MeshFilter(mesh) + + # Create an energy group filter as well + energy_filter = openmc.EnergyFilter(group_edges) + + # Now use the mesh filter in a tally and indicate what scores are desired + tally = openmc.Tally(name="Mesh tally") + tally.filters = [mesh_filter, energy_filter] + tally.scores = ['flux', 'fission', 'nu-fission'] + tally.estimator = 'analog' + + # Instantiate a Tallies collection and export to XML + tallies = openmc.Tallies([tally]) + + ############################################################################### + # Exporting to OpenMC model + ############################################################################### + + model = openmc.Model() + model.geometry = geometry + model.materials = materials + model.settings = settings + model.tallies = tallies + return model + + +def test_random_ray_vacuum(): + harness = MGXSTestHarness('statepoint.10.h5', random_ray_model()) + harness.main() diff --git a/tests/testing_harness.py b/tests/testing_harness.py index 40c9d37d806..81527452b84 100644 --- a/tests/testing_harness.py +++ b/tests/testing_harness.py @@ -384,6 +384,63 @@ def _get_results(self): return super()._get_results(True) +class TolerantPyAPITestHarness(PyAPITestHarness): + """Specialized harness for running tests that involve significant levels + of floating point non-associativity when using shared memory parallelism + due to single precision usage (e.g., as in the random ray solver). + + """ + def _are_files_equal(self, actual_path, expected_path, tolerance): + def isfloat(value): + try: + float(value) + return True + except ValueError: + return False + + def tokenize(line): + return line.strip().split() + + def compare_tokens(token1, token2): + if isfloat(token1) and isfloat(token2): + float1, float2 = float(token1), float(token2) + return abs(float1 - float2) <= tolerance * max(abs(float1), abs(float2)) + else: + return token1 == token2 + + expected = open(expected_path).readlines() + actual = open(actual_path).readlines() + + if len(expected) != len(actual): + return False + + for line1, line2 in zip(expected, actual): + tokens1 = tokenize(line1) + tokens2 = tokenize(line2) + + if len(tokens1) != len(tokens2): + return False + + for token1, token2 in zip(tokens1, tokens2): + if not compare_tokens(token1, token2): + return False + + return True + + def _compare_results(self): + """Make sure the current results agree with the reference.""" + compare = self._are_files_equal('results_test.dat', 'results_true.dat', 1e-6) + if not compare: + expected = open('results_true.dat').readlines() + actual = open('results_test.dat').readlines() + diff = unified_diff(expected, actual, 'results_true.dat', + 'results_test.dat') + print('Result differences:') + print(''.join(colorize(diff))) + os.rename('results_test.dat', 'results_error.dat') + assert compare, 'Results do not agree' + + class PlotTestHarness(TestHarness): """Specialized TestHarness for running OpenMC plotting tests.""" def __init__(self, plot_names, voxel_convert_checks=[]): diff --git a/tests/unit_tests/test_settings.py b/tests/unit_tests/test_settings.py index 30930ecdff2..650bfd18680 100644 --- a/tests/unit_tests/test_settings.py +++ b/tests/unit_tests/test_settings.py @@ -58,6 +58,13 @@ def test_export_to_xml(run_in_tmpdir): s.electron_treatment = 'led' s.write_initial_source = True s.weight_window_checkpoints = {'surface': True, 'collision': False} + s.random_ray = { + 'distance_inactive': 10.0, + 'distance_active': 100.0, + 'ray_source': openmc.IndependentSource( + space=openmc.stats.Box((-1., -1., -1.), (1., 1., 1.)) + ) + } s.max_particle_events = 100 @@ -131,3 +138,7 @@ def test_export_to_xml(run_in_tmpdir): assert vol.upper_right == (10., 10., 10.) assert s.weight_window_checkpoints == {'surface': True, 'collision': False} assert s.max_particle_events == 100 + assert s.random_ray['distance_inactive'] == 10.0 + assert s.random_ray['distance_active'] == 100.0 + assert s.random_ray['ray_source'].space.lower_left == [-1., -1., -1.] + assert s.random_ray['ray_source'].space.upper_right == [1., 1., 1.]