From 679781da0a42e5a4ab1b49b2ae8279b5b30cc00c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 21 Jan 2016 15:43:49 -0600 Subject: [PATCH 01/24] Disallow duplicate scores in tallies --- src/ace.F90 | 2 +- src/endf.F90 | 47 +++++++++++++++++++++++++++++++++++++++++++ src/input_xml.F90 | 27 +++++++++++++++++++++++++ src/state_point.F90 | 49 +-------------------------------------------- src/summary.F90 | 49 +-------------------------------------------- 5 files changed, 77 insertions(+), 97 deletions(-) diff --git a/src/ace.F90 b/src/ace.F90 index e97338b558..2947ff9de3 100644 --- a/src/ace.F90 +++ b/src/ace.F90 @@ -3,7 +3,7 @@ module ace use ace_header, only: Nuclide, Reaction, SAlphaBeta, XsListing, & DistEnergy use constants - use endf, only: reaction_name, is_fission, is_disappearance + use endf, only: is_fission, is_disappearance use error, only: fatal_error, warning use fission, only: nu_total use global diff --git a/src/endf.F90 b/src/endf.F90 index ba324722c3..64f26539a9 100644 --- a/src/endf.F90 +++ b/src/endf.F90 @@ -17,6 +17,53 @@ contains character(20) :: string select case (MT) + ! Special reactions for tallies + case (SCORE_FLUX) + string = "flux" + case (SCORE_TOTAL) + string = "total" + case (SCORE_SCATTER) + string = "scatter" + case (SCORE_NU_SCATTER) + string = "nu-scatter" + case (SCORE_SCATTER_N) + string = "scatter-n" + case (SCORE_SCATTER_PN) + string = "scatter-pn" + case (SCORE_NU_SCATTER_N) + string = "nu-scatter-n" + case (SCORE_NU_SCATTER_PN) + string = "nu-scatter-pn" + case (SCORE_TRANSPORT) + string = "transport" + case (SCORE_N_1N) + string = "n1n" + case (SCORE_ABSORPTION) + string = "absorption" + case (SCORE_FISSION) + string = "fission" + case (SCORE_NU_FISSION) + string = "nu-fission" + case (SCORE_DELAYED_NU_FISSION) + string = "delayed-nu-fission" + case (SCORE_KAPPA_FISSION) + string = "kappa-fission" + case (SCORE_CURRENT) + string = "current" + case (SCORE_FLUX_YN) + string = "flux-yn" + case (SCORE_TOTAL_YN) + string = "total-yn" + case (SCORE_SCATTER_YN) + string = "scatter-yn" + case (SCORE_NU_SCATTER_YN) + string = "nu-scatter-yn" + case (SCORE_EVENTS) + string = "events" + case (SCORE_INVERSE_VELOCITY) + string = "inverse-velocity" + + ! Normal ENDF-based reactions case (TOTAL_XS) string = '(n,total)' case (ELASTIC) diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 1427458901..ec8a8a5a15 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -5,6 +5,7 @@ module input_xml use dict_header, only: DictIntInt, ElemKeyValueCI use distribution_multivariate use distribution_univariate + use endf, only: reaction_name use energy_grid, only: grid_method, n_log_bins use error, only: fatal_error, warning use geometry_header, only: Cell, Lattice, RectLattice, HexLattice @@ -3426,6 +3427,32 @@ contains ! Deallocate temporary string array of scores deallocate(sarray) + + ! Check that no duplicate scores exist + j = 1 + do while (j < n_scores) + ! Determine number of bins for scores with expansions + n_order = t % moment_order(j) + select case (t % score_bins(j)) + case (SCORE_SCATTER_PN, SCORE_NU_SCATTER_PN) + n_bins = n_order + 1 + case (SCORE_FLUX_YN, SCORE_TOTAL_YN, SCORE_SCATTER_YN, & + SCORE_NU_SCATTER_YN) + n_bins = (n_order + 1)**2 + case default + n_bins = 1 + end select + + do k = j + n_bins, n_scores + if (t % score_bins(j) == t % score_bins(k) .and. & + t % moment_order(j) == t % moment_order(k)) then + call fatal_error("Duplicate score of type '" // trim(& + reaction_name(t % score_bins(j))) // "' found in tally " & + // trim(to_str(t % id))) + end if + end do + j = j + n_bins + end do else call fatal_error("No specified on tally " & &// trim(to_str(t % id)) // ".") diff --git a/src/state_point.F90 b/src/state_point.F90 index e89cdf12a8..70ee2d06ad 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -310,54 +310,7 @@ contains call write_dataset(tally_group, "n_score_bins", tally%n_score_bins) allocate(str_array(size(tally%score_bins))) do j = 1, size(tally%score_bins) - select case(tally%score_bins(j)) - case (SCORE_FLUX) - str_array(j) = "flux" - case (SCORE_TOTAL) - str_array(j) = "total" - case (SCORE_SCATTER) - str_array(j) = "scatter" - case (SCORE_NU_SCATTER) - str_array(j) = "nu-scatter" - case (SCORE_SCATTER_N) - str_array(j) = "scatter-n" - case (SCORE_SCATTER_PN) - str_array(j) = "scatter-pn" - case (SCORE_NU_SCATTER_N) - str_array(j) = "nu-scatter-n" - case (SCORE_NU_SCATTER_PN) - str_array(j) = "nu-scatter-pn" - case (SCORE_TRANSPORT) - str_array(j) = "transport" - case (SCORE_N_1N) - str_array(j) = "n1n" - case (SCORE_ABSORPTION) - str_array(j) = "absorption" - case (SCORE_FISSION) - str_array(j) = "fission" - case (SCORE_NU_FISSION) - str_array(j) = "nu-fission" - case (SCORE_DELAYED_NU_FISSION) - str_array(j) = "delayed-nu-fission" - case (SCORE_KAPPA_FISSION) - str_array(j) = "kappa-fission" - case (SCORE_CURRENT) - str_array(j) = "current" - case (SCORE_FLUX_YN) - str_array(j) = "flux-yn" - case (SCORE_TOTAL_YN) - str_array(j) = "total-yn" - case (SCORE_SCATTER_YN) - str_array(j) = "scatter-yn" - case (SCORE_NU_SCATTER_YN) - str_array(j) = "nu-scatter-yn" - case (SCORE_EVENTS) - str_array(j) = "events" - case (SCORE_INVERSE_VELOCITY) - str_array(j) = "inverse-velocity" - case default - str_array(j) = reaction_name(tally%score_bins(j)) - end select + str_array(j) = reaction_name(tally%score_bins(j)) end do call write_dataset(tally_group, "score_bins", str_array) call write_dataset(tally_group, "n_user_score_bins", tally%n_user_score_bins) diff --git a/src/summary.F90 b/src/summary.F90 index 85d0146923..c31068eb9f 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -639,54 +639,7 @@ contains call write_dataset(tally_group, "n_score_bins", t%n_score_bins) allocate(str_array(size(t%score_bins))) do j = 1, size(t%score_bins) - select case(t%score_bins(j)) - case (SCORE_FLUX) - str_array(j) = "flux" - case (SCORE_TOTAL) - str_array(j) = "total" - case (SCORE_SCATTER) - str_array(j) = "scatter" - case (SCORE_NU_SCATTER) - str_array(j) = "nu-scatter" - case (SCORE_SCATTER_N) - str_array(j) = "scatter-n" - case (SCORE_SCATTER_PN) - str_array(j) = "scatter-pn" - case (SCORE_NU_SCATTER_N) - str_array(j) = "nu-scatter-n" - case (SCORE_NU_SCATTER_PN) - str_array(j) = "nu-scatter-pn" - case (SCORE_TRANSPORT) - str_array(j) = "transport" - case (SCORE_N_1N) - str_array(j) = "n1n" - case (SCORE_ABSORPTION) - str_array(j) = "absorption" - case (SCORE_FISSION) - str_array(j) = "fission" - case (SCORE_NU_FISSION) - str_array(j) = "nu-fission" - case (SCORE_DELAYED_NU_FISSION) - str_array(j) = "delayed-nu-fission" - case (SCORE_KAPPA_FISSION) - str_array(j) = "kappa-fission" - case (SCORE_CURRENT) - str_array(j) = "current" - case (SCORE_FLUX_YN) - str_array(j) = "flux-yn" - case (SCORE_TOTAL_YN) - str_array(j) = "total-yn" - case (SCORE_SCATTER_YN) - str_array(j) = "scatter-yn" - case (SCORE_NU_SCATTER_YN) - str_array(j) = "nu-scatter-yn" - case (SCORE_EVENTS) - str_array(j) = "events" - case (SCORE_INVERSE_VELOCITY) - str_array(j) = "inverse-velocity" - case default - str_array(j) = reaction_name(t%score_bins(j)) - end select + str_array(j) = reaction_name(t%score_bins(j)) end do call write_dataset(tally_group, "score_bins", str_array) From 0e1e67bc2edd1c0e84d2212f804c7e5dedecedf2 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 22 Jan 2016 07:18:13 -0600 Subject: [PATCH 02/24] Improve documentation on tally scores --- docs/source/_static/theme_overrides.css | 10 + docs/source/conf.py | 4 +- docs/source/usersguide/input.rst | 329 ++++++++++++++++-------- 3 files changed, 237 insertions(+), 106 deletions(-) create mode 100644 docs/source/_static/theme_overrides.css diff --git a/docs/source/_static/theme_overrides.css b/docs/source/_static/theme_overrides.css new file mode 100644 index 0000000000..7c1a520223 --- /dev/null +++ b/docs/source/_static/theme_overrides.css @@ -0,0 +1,10 @@ +/* override table width restrictions */ +.wy-table-responsive table td, .wy-table-responsive table th { + white-space: normal; +} + +.wy-table-responsive { + margin-bottom: 24px; + max-width: 100%; + overflow: visible; +} diff --git a/docs/source/conf.py b/docs/source/conf.py index 32154fa60f..65db07b25e 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -152,7 +152,9 @@ html_title = "OpenMC Documentation" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -#html_static_path = ['_static'] +html_static_path = ['_static'] + +html_context = {'css_files': ['_static/theme_overrides.css']} # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. diff --git a/docs/source/usersguide/input.rst b/docs/source/usersguide/input.rst index 30e9ed07b9..ca16c8fef6 100644 --- a/docs/source/usersguide/input.rst +++ b/docs/source/usersguide/input.rst @@ -1475,114 +1475,233 @@ The ```` element accepts the following sub-elements: *Default*: ``tracklength`` but will revert to ``analog`` if necessary. :scores: - A space-separated list of the desired responses to be accumulated. Accepted - options are "flux", "total", "scatter", "absorption", "fission", - "nu-fission", "delayed-nu-fission", "kappa-fission", "nu-scatter", - "scatter-N", "scatter-PN", "scatter-YN", "nu-scatter-N", "nu-scatter-PN", - "nu-scatter-YN", "flux-YN", "total-YN", "current", "inverse-velocity" and - "events". These correspond to the following physical quantities: + A space-separated list of the desired responses to be accumulated. The accepted + options are listed in the following table: - :flux: - Total flux in particle-cm per source particle. + .. table:: Score types available in OpenMC - .. note:: - The ``analog`` estimator is actually identical to the ``collision`` - estimator for the flux score. + +----------------------+---------------------------------------------------+ + |Score | Description | + +======================+===================================================+ + |flux |Total flux in particle-cm per source particle. | + | | | + +----------------------+---------------------------------------------------+ + |total |Total reaction rate in reactions per source | + | |particle. | + +----------------------+---------------------------------------------------+ + |scatter |Total scattering rate. Can also be identified with | + | |the "scatter-0" response type. Units are reactions | + | |per source particle. | + +----------------------+---------------------------------------------------+ + |absorption |Total absorption rate. This accounts for all | + | |reactions which do not produce secondary | + | |neutrons. Units are reactions per source particle. | + +----------------------+---------------------------------------------------+ + |fission |Total fission rate in reactions per source | + | |particle. | + +----------------------+---------------------------------------------------+ + |nu-fission |Total production of neutrons due to fission. Units | + | |are neutrons produced per source neutron. | + +----------------------+---------------------------------------------------+ + |delayed-nu-fission |Total production of delayed neutrons due to | + | |fission. Units are neutrons produced per source | + | |neutron. | + +----------------------+---------------------------------------------------+ + |kappa-fission |The recoverable energy production rate due to | + | |fission. The recoverable energy is defined as the | + | |fission product kinetic energy, prompt and delayed | + | |neutron kinetic energies, prompt and delayed | + | |:math:`\gamma`-ray total energies, and the total | + | |energy released by the delayed :math:`\beta` | + | |particles. The neutrino energy does not contribute | + | |to this response. The prompt and delayed | + | |:math:`\gamma`-rays are assumed to deposit their | + | |energy locally. Units are MeV per source particle. | + +----------------------+---------------------------------------------------+ + |scatter-N |Tally the N\ :sup:`th` \ scattering moment, where N| + | |is the Legendre expansion order of the change in | + | |particle angle :math:`\left(\mu\right)`. N must be | + | |between 0 and 10. As an example, tallying the 2\ | + | |:sup:`nd` \ scattering moment would be specified as| + | |``scatter-2``. Units are reactions| + | |per source particle. | + +----------------------+---------------------------------------------------+ + |scatter-PN |Tally all of the scattering moments from order 0 to| + | |N, where N is the Legendre expansion order of the | + | |change in particle angle | + | |:math:`\left(\mu\right)`. That is, "scatter-P1" is | + | |equivalent to requesting tallies of "scatter-0" and| + | |"scatter-1". Like for "scatter-N", N must be | + | |between 0 and 10. As an example, tallying up to the| + | |2\ :sup:`nd` \ scattering moment would be specified| + | |as `` scatter-P2 ``. Units are | + | |reactions per source particle. | + +----------------------+---------------------------------------------------+ + |scatter-YN |"scatter-YN" is similar to "scatter-PN" except an | + | |additional expansion is performed for the incoming | + | |particle direction :math:`\left(\Omega\right)` | + | |using the real spherical harmonics. This is useful| + | |for performing angular flux moment weighting of the| + | |scattering moments. Like "scatter-PN", "scatter-YN"| + | |will tally all of the moments from order 0 to N; N | + | |again must be between 0 and 10. Units are reactions| + | |per source particle. | + +----------------------+---------------------------------------------------+ + |nu-scatter, |These scores are similar in functionality to their | + |nu-scatter-N, |``scatter*`` equivalents except the total | + |nu-scatter-PN, |production of neutrons due to scattering is scored | + |nu-scatter-YN |vice simply the scattering rate. This accounts for | + | |multiplicity from (n,2n), (n,3n), and (n,4n) | + | |reactions. Units are neutrons produced per source | + | |particle. | + +----------------------+---------------------------------------------------+ + |flux-YN |Spherical harmonic expansion of the direction of | + | |motion :math:`\left(\Omega\right)` of the total | + | |flux. This score will tally all of the harmonic | + | |moments of order 0 to N. N must be between 0 and | + | |10. Units are particle-cm per source particle. | + +----------------------+---------------------------------------------------+ + |total-YN |The total reaction rate expanded via spherical | + | |harmonics about the direction of motion of the | + | |neutron, :math:`\Omega`. This score will tally all | + | |of the harmonic moments of order 0 to N. N must be| + | |between 0 and 10. Units are reactions per source | + | |particle. | + +----------------------+---------------------------------------------------+ + |current |Partial currents on the boundaries of each cell in | + | |a mesh. Units are particles per source | + | |particle. Note that this score can only be used if | + | |a mesh filter has been specified. Furthermore, it | + | |may not be used in conjunction with any other | + | |score. | + +----------------------+---------------------------------------------------+ + |inverse-velocity |The flux-weighted inverse velocity where the | + | |velocity is in units of centimeters per second. | + +----------------------+---------------------------------------------------+ + |events |Number of scoring events. Units are events per | + | |source particle. | + +----------------------+---------------------------------------------------+ + |elastic |Elastic scattering reaction rate. Units are | + | |reactions per source particle. | + +----------------------+---------------------------------------------------+ + |(n,2nd) |(n,2nd) reaction rate. Units are reactions per | + | |source particle. | + +----------------------+---------------------------------------------------+ + |(n,2n) |(n,2n) reaction rate. Units are reactions per | + | |source particle. | + +----------------------+---------------------------------------------------+ + |(n,3n) |(n,3n) reaction rate. Units are reactions per | + | |source particle. | + +----------------------+---------------------------------------------------+ + |(n,na) |(n,n\ :math:`\alpha`\ ) reaction rate. Units are | + | |reactions per source particle. | + +----------------------+---------------------------------------------------+ + |(n,n3a) |(n,n3\ :math:`\alpha`\ ) reaction rate. Units are | + | |reactions per source particle. | + +----------------------+---------------------------------------------------+ + |(n,2na) |(n,2n\ :math:`\alpha`\ ) reaction rate. Units are | + | |reactions per source particle. | + +----------------------+---------------------------------------------------+ + |(n,3na) |(n,3n\ :math:`\alpha`\ ) reaction rate. Units are | + | |reactions per source particle. | + +----------------------+---------------------------------------------------+ + |(n,np) |(n,np) reaction rate. Units are reactions per | + | |source particle. | + +----------------------+---------------------------------------------------+ + |(n,n2a) |(n,n2\ :math:`\alpha`\ ) reaction rate. Units are | + | |reactions per source particle. | + +----------------------+---------------------------------------------------+ + |(n,2n2a) |(n,2n2\ :math:`\alpha`\ ) reaction rate. Units are | + | |reactions per source particle. | + +----------------------+---------------------------------------------------+ + |(n,nd) |(n,nd) reaction rate. Units are reactions per | + | |source particle. | + +----------------------+---------------------------------------------------+ + |(n,nt) |(n,nt) reaction rate. Units are reactions per | + | |source particle. | + +----------------------+---------------------------------------------------+ + |(n,nHe-3) |(n,n\ :sup:`3`\ He) reaction rate. Units are | + | |reactions per source particle. | + +----------------------+---------------------------------------------------+ + |(n,nd2a) |(n,nd2\ :math:`\alpha`\ ) reaction rate. Units are | + | |reactions per source particle. | + +----------------------+---------------------------------------------------+ + |(n,nt2a) |(n,nt2\ :math:`\alpha`\ ) reaction rate. Units are | + | |reactions per source particle. | + +----------------------+---------------------------------------------------+ + |(n,4n) |(n,4n) reaction rate. Units are reactions per | + | |source particle. | + +----------------------+---------------------------------------------------+ + |(n,2np) |(n,2np) reaction rate. Units are reactions per | + | |source particle. | + +----------------------+---------------------------------------------------+ + |(n,3np) |(n,3np) reaction rate. Units are reactions per | + | |source particle. | + +----------------------+---------------------------------------------------+ + |(n,n2p) |(n,n2p) reaction rate. Units are reactions per | + | |source particle. | + +----------------------+---------------------------------------------------+ + |(n,n*X*) |Level inelastic scattering reaction rate. The *X* | + | |indicates what which inelastic level, e.g., (n,n3) | + | |is third-level inelastic scattering. Units are | + | |reactions per source particle. | + +----------------------+---------------------------------------------------+ + |(n,nc) |Continuum level inelastic scattering reaction | + | |rate. Units are reactions per source particle. | + +----------------------+---------------------------------------------------+ + |(n,gamma) |Radiative capture reaction rate. Units are | + | |reactions per source particle. | + +----------------------+---------------------------------------------------+ + |(n,p) |(n,p) reaction rate. Units are reactions per source| + | |particle. | + +----------------------+---------------------------------------------------+ + |(n,d) |(n,d) reaction rate. Units are reactions per source| + | |particle. | + +----------------------+---------------------------------------------------+ + |(n,t) |(n,t) reaction rate. Units are reactions per source| + | |particle. | + +----------------------+---------------------------------------------------+ + |(n,3He) |(n,\ :sup:`3`\ He) reaction rate. Units are | + | |reactions per source particle. | + +----------------------+---------------------------------------------------+ + |(n,a) |(n,\ :math:`\alpha`\ ) reaction rate. Units are | + | |reactions per source particle. | + +----------------------+---------------------------------------------------+ + |(n,2a) |(n,2\ :math:`\alpha`\ ) reaction rate. Units are | + | |reactions per source particle. | + +----------------------+---------------------------------------------------+ + |(n,3a) |(n,3\ :math:`\alpha`\ ) reaction rate. Units are | + | |reactions per source particle. | + +----------------------+---------------------------------------------------+ + |(n,2p) |(n,2p) reaction rate. Units are reactions per | + | |source particle. | + +----------------------+---------------------------------------------------+ + |(n,pa) |(n,p\ :math:`\alpha`\ ) reaction rate. Units are | + | |reactions per source particle. | + +----------------------+---------------------------------------------------+ + |(n,t2a) |(n,t2\ :math:`\alpha`\ ) reaction rate. Units are | + | |reactions per source particle. | + +----------------------+---------------------------------------------------+ + |(n,d2a) |(n,d2\ :math:`\alpha`\ ) reaction rate. Units are | + | |reactions per source particle. | + +----------------------+---------------------------------------------------+ + |(n,pd) |(n,pd) reaction rate. Units are reactions per | + | |source particle. | + +----------------------+---------------------------------------------------+ + |(n,pt) |(n,pt) reaction rate. Units are reactions per | + | |source particle. | + +----------------------+---------------------------------------------------+ + |(n,da) |(n,d\ :math:`\alpha`\ ) reaction rate. Units are | + | |reactions per source particle. | + +----------------------+---------------------------------------------------+ + |*Arbitrary integer* |An arbitrary integer is interpreted to mean the | + | |reaction rate for a reaction with a given ENDF MT | + | |number. Units are reactions per source particle. | + +----------------------+---------------------------------------------------+ - :total: - Total reaction rate in reactions per source particle. - - :scatter: - Total scattering rate. Can also be identified with the ``scatter-0`` - response type. Units are reactions per source particle. - - :absorption: - Total absorption rate. This accounts for all reactions which do not - produce secondary neutrons. Units are reactions per source particle. - - :fission: - Total fission rate in reactions per source particle. - - :nu-fission: - Total production of neutrons due to fission. Units are neutrons produced - per source neutron. - - :delayed-nu-fission: - Total production of delayed neutrons due to fission. Units are neutrons produced - per source neutron. - - :kappa-fission: - The recoverable energy production rate due to fission. The recoverable - energy is defined as the fission product kinetic energy, prompt and - delayed neutron kinetic energies, prompt and delayed :math:`\gamma`-ray - total energies, and the total energy released by the delayed :math:`\beta` - particles. The neutrino energy does not contribute to this response. The - prompt and delayed :math:`\gamma`-rays are assumed to deposit their energy - locally. Units are MeV per source particle. - - :scatter-N: - Tally the N\ :sup:`th` \ scattering moment, where N is the Legendre - expansion order of the change in particle angle :math:`\left(\mu\right)`. - N must be between 0 and 10. As an example, tallying the 2\ :sup:`nd` \ - scattering moment would be specified as `` scatter-2 - ``. Units are reactions per source particle. - - :scatter-PN: - Tally all of the scattering moments from order 0 to N, where N is the - Legendre expansion order of the change in particle angle - :math:`\left(\mu\right)`. That is, ``scatter-P1`` is equivalent to - requesting tallies of ``scatter-0`` and ``scatter-1``. Like for - ``scatter-N``, N must be between 0 and 10. As an example, tallying up to - the 2\ :sup:`nd` \ scattering moment would be specified as `` - scatter-P2 ``. Units are reactions per source particle. - - :scatter-YN: - ``scatter-YN`` is similar to ``scatter-PN`` except an additional expansion - is performed for the incoming particle direction - :math:`\left(\Omega\right)` using the real spherical harmonics. This is - useful for performing angular flux moment weighting of the scattering - moments. Like ``scatter-PN``, ``scatter-YN`` will tally all of the moments - from order 0 to N; N again must be between 0 and 10. Units are reactions - per source particle. - - :nu-scatter, nu-scatter-N, nu-scatter-PN, nu-scatter-YN: - These scores are similar in functionality to their ``scatter*`` - equivalents except the total production of neutrons due to scattering is - scored vice simply the scattering rate. This accounts for multiplicity - from (n,2n), (n,3n), and (n,4n) reactions. Units are neutrons produced per - source particle. - - :flux-YN: - Spherical harmonic expansion of the direction of motion - :math:`\left(\Omega\right)` of the total flux. This score will tally all - of the harmonic moments of order 0 to N. N must be between 0 - and 10. Units are particle-cm per source particle. - - :total-YN: - The total reaction rate expanded via spherical harmonics about the - direction of motion of the neutron, :math:`\Omega`. - This score will tally all of the harmonic moments of order 0 to N. N must - be between 0 and 10. Units are reactions per source particle. - - :current: - Partial currents on the boundaries of each cell in a mesh. Units are - particles per source particle. - - .. note:: - This score can only be used if a mesh filter has been - specified. Furthermore, it may not be used in conjunction with any - other score. - - :inverse-velocity: - The flux-weighted inverse velocity where the velocity is in units of - centimeters per second. - - .. note:: - The ``analog`` estimator is actually identical to the ``collision`` - estimator for the inverse-velocity score. - - :events: - Number of scoring events. Units are events per source particle. + .. note:: + The ``analog`` estimator is actually identical to the ``collision`` + estimator for the flux and inverse-velocity scores. :trigger: Precision trigger applied to all filter bins and nuclides for this tally. From 79dea15ddfbe9b1726cb166af34cc12d37ca5900 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 13 Nov 2015 12:59:26 -0600 Subject: [PATCH 03/24] Allow fission to create secondary neutrons in fixed source simulations. --- src/particle_header.F90 | 2 +- src/physics.F90 | 36 +++++++++++++++++++++--------------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/particle_header.F90 b/src/particle_header.F90 index 0b9b251ee5..30f5e8bb64 100644 --- a/src/particle_header.F90 +++ b/src/particle_header.F90 @@ -86,7 +86,7 @@ module particle_header logical :: write_track = .false. ! Secondary particles created - integer :: n_secondary = 0 + integer(8) :: n_secondary = 0 type(Bank) :: secondary_bank(MAX_SECONDARY) contains diff --git a/src/physics.F90 b/src/physics.F90 index 31eb981abb..03a4cb6086 100644 --- a/src/physics.F90 +++ b/src/physics.F90 @@ -88,9 +88,14 @@ contains ! change when sampling fission sites. The following block handles all ! absorption (including fission) - if (nuc % fissionable .and. run_mode == MODE_EIGENVALUE) then + if (nuc % fissionable) then call sample_fission(i_nuclide, i_reaction) - call create_fission_sites(p, i_nuclide, i_reaction) + if (run_mode == MODE_EIGENVALUE) then + call create_fission_sites(p, i_nuclide, i_reaction, fission_bank, n_bank) + elseif (run_mode == MODE_FIXEDSOURCE) then + call create_fission_sites(p, i_nuclide, i_reaction, & + p%secondary_bank, p%n_secondary) + end if end if ! If survival biasing is being used, the following subroutine adjusts the @@ -1071,10 +1076,12 @@ contains ! neutrons produced from fission and creates appropriate bank sites. !=============================================================================== - subroutine create_fission_sites(p, i_nuclide, i_reaction) + subroutine create_fission_sites(p, i_nuclide, i_reaction, bank_array, size_bank) type(Particle), intent(inout) :: p integer, intent(in) :: i_nuclide integer, intent(in) :: i_reaction + type(Bank), intent(inout) :: bank_array(:) + integer(8), intent(inout) :: size_bank integer :: nu_d(MAX_DELAYED_GROUPS) ! number of delayed neutrons born integer :: i ! loop index @@ -1124,26 +1131,26 @@ contains end if ! Check for fission bank size getting hit - if (n_bank + nu > size(fission_bank)) then + if (size_bank + nu > size(bank_array)) then if (master) call warning("Maximum number of sites in fission bank & &reached. This can result in irreproducible results using different & &numbers of processes/threads.") end if ! Bank source neutrons - if (nu == 0 .or. n_bank == size(fission_bank)) return + if (nu == 0 .or. size_bank == size(bank_array)) return ! Initialize counter of delayed neutrons encountered for each delayed group ! to zero. nu_d(:) = 0 p % fission = .true. ! Fission neutrons will be banked - do i = int(n_bank,4) + 1, int(min(n_bank + nu, int(size(fission_bank),8)),4) + do i = int(size_bank,4) + 1, int(min(size_bank + nu, int(size(bank_array),8)),4) ! Bank source neutrons by copying particle data - fission_bank(i) % xyz = p % coord(1) % xyz + bank_array(i) % xyz = p % coord(1) % xyz ! Set weight of fission bank site - fission_bank(i) % wgt = ONE/weight + bank_array(i) % wgt = ONE/weight ! Sample cosine of angle -- fission neutrons are always emitted ! isotropically. Sometimes in ACE data, fission reactions actually have @@ -1153,17 +1160,16 @@ contains ! Sample azimuthal angle uniformly in [0,2*pi) phi = TWO*PI*prn() - fission_bank(i) % uvw(1) = mu - fission_bank(i) % uvw(2) = sqrt(ONE - mu*mu) * cos(phi) - fission_bank(i) % uvw(3) = sqrt(ONE - mu*mu) * sin(phi) + bank_array(i) % uvw(1) = mu + bank_array(i) % uvw(2) = sqrt(ONE - mu*mu) * cos(phi) + bank_array(i) % uvw(3) = sqrt(ONE - mu*mu) * sin(phi) ! Sample secondary energy distribution for fission reaction and set energy ! in fission bank - fission_bank(i) % E = sample_fission_energy(nuc, nuc%reactions(& - i_reaction), p) + bank_array(i) % E = sample_fission_energy(nuc, nuc%reactions(i_reaction), p) ! Set the delayed group of the neutron - fission_bank(i) % delayed_group = p % delayed_group + bank_array(i) % delayed_group = p % delayed_group ! Increment the number of neutrons born delayed if (p % delayed_group > 0) then @@ -1172,7 +1178,7 @@ contains end do ! increment number of bank sites - n_bank = min(n_bank + nu, int(size(fission_bank),8)) + size_bank = min(size_bank + nu, int(size(bank_array),8)) ! Store total and delayed weight banked for analog fission tallies p % n_bank = nu From 0e0984a5ff770ce2274ad1d1c5b0c98e8c621e48 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 Nov 2015 14:54:52 -0600 Subject: [PATCH 04/24] Check if secondary particle bank limit is reached during subcritical multiplication --- src/physics.F90 | 16 ++++++++++++---- src/tracking.F90 | 1 + 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/physics.F90 b/src/physics.F90 index 03a4cb6086..c6ecf4fe66 100644 --- a/src/physics.F90 +++ b/src/physics.F90 @@ -1130,11 +1130,19 @@ contains nu = int(nu_t) + 1 end if - ! Check for fission bank size getting hit + ! Check for bank size getting hit. For fixed source calculations, this is a + ! fatal error. For eigenvalue calculations, it just means that k-effective + ! was too high for a single batch. if (size_bank + nu > size(bank_array)) then - if (master) call warning("Maximum number of sites in fission bank & - &reached. This can result in irreproducible results using different & - &numbers of processes/threads.") + if (run_mode == MODE_FIXEDSOURCE) then + call fatal_error("Secondary particle bank size limit reached. If you & + &are running a subcritical multiplication problem, k-effective & + &may be too close to one.") + else + if (master) call warning("Maximum number of sites in fission bank & + &reached. This can result in irreproducible results using different & + &numbers of processes/threads.") + end if end if ! Bank source neutrons diff --git a/src/tracking.F90 b/src/tracking.F90 index 2e4503e139..7cc761055b 100644 --- a/src/tracking.F90 +++ b/src/tracking.F90 @@ -202,6 +202,7 @@ contains if (p % n_secondary > 0) then call p % initialize_from_source(p % secondary_bank(p % n_secondary)) p % n_secondary = p % n_secondary - 1 + n_event = 0 ! Enter new particle in particle track file if (p % write_track) call add_particle_track() From 2fc95bb5633bda3fe282ed5c13ee4896cd347eb7 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 25 Jan 2016 09:12:55 -0600 Subject: [PATCH 05/24] Include fissionable material in fixed source test --- tests/test_fixed_source/materials.xml | 1 + tests/test_fixed_source/results_true.dat | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/test_fixed_source/materials.xml b/tests/test_fixed_source/materials.xml index 5242021d34..ab7a76bc00 100644 --- a/tests/test_fixed_source/materials.xml +++ b/tests/test_fixed_source/materials.xml @@ -4,6 +4,7 @@ + diff --git a/tests/test_fixed_source/results_true.dat b/tests/test_fixed_source/results_true.dat index 0940301886..b3def050e8 100644 --- a/tests/test_fixed_source/results_true.dat +++ b/tests/test_fixed_source/results_true.dat @@ -1,6 +1,6 @@ tally 1: -4.538791E+02 -2.073271E+04 +4.563929E+02 +2.091711E+04 leakage: -9.830000E+00 -9.663900E+00 +9.780000E+00 +9.566400E+00 From e570f53b22c14ad04370d992eecca1c5a8b829fc Mon Sep 17 00:00:00 2001 From: "wbinventor@gmail.com" Date: Wed, 27 Jan 2016 11:45:09 -0500 Subject: [PATCH 06/24] Removed elementwise comparisons for subdomains and groups parameters to MGXS class methods --- openmc/mgxs/mgxs.py | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index 0eec6d4585..bfa8b02c5c 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -673,14 +673,14 @@ class MGXS(object): filter_bins = [] # Construct a collection of the domain filter bins - if subdomains != 'all': + if not isinstance(subdomains, basestring): cv.check_iterable_type('subdomains', subdomains, Integral) for subdomain in subdomains: filters.append(self.domain_type) filter_bins.append((subdomain,)) # Construct list of energy group bounds tuples for all requested groups - if groups != 'all': + if not isinstance(groups, basestring): cv.check_iterable_type('groups', groups, Integral) for group in groups: filters.append('energy') @@ -838,7 +838,7 @@ class MGXS(object): """ # Construct a collection of the subdomain filter bins to average across - if subdomains != 'all': + if not isinstance(subdomains, basestring): cv.check_iterable_type('subdomains', subdomains, Integral) elif self.domain_type == 'distribcell': subdomains = np.arange(self.num_subdomains) @@ -881,7 +881,7 @@ class MGXS(object): """ # Construct a collection of the subdomains to report - if subdomains != 'all': + if not isinstance(subdomains, basestring): cv.check_iterable_type('subdomains', subdomains, Integral) elif self.domain_type == 'distribcell': subdomains = np.arange(self.num_subdomains, dtype=np.int) @@ -1010,7 +1010,7 @@ class MGXS(object): xs_results = h5py.File(filename, 'w') # Construct a collection of the subdomains to report - if subdomains != 'all': + if not isinstance(subdomains, basestring): cv.check_iterable_type('subdomains', subdomains, Integral) elif self.domain_type == 'distribcell': subdomains = np.arange(self.num_subdomains, dtype=np.int) @@ -1192,7 +1192,7 @@ class MGXS(object): """ - if groups != 'all': + if not isinstance(groups, basestring): cv.check_iterable_type('groups', groups, Integral) if nuclides != 'all' and nuclides != 'sum': cv.check_iterable_type('nuclides', nuclides, basestring) @@ -1252,7 +1252,7 @@ class MGXS(object): columns = ['group in'] # Select out those groups the user requested - if groups != 'all': + if not isinstance(groups, basestring): if 'group in' in df: df = df[df['group in'].isin(groups)] if 'group out' in df: @@ -1789,21 +1789,21 @@ class ScatterMatrixXS(MGXS): filter_bins = [] # Construct a collection of the domain filter bins - if subdomains != 'all': + if not isinstance(subdomains, basestring): cv.check_iterable_type('subdomains', subdomains, Integral) for subdomain in subdomains: filters.append(self.domain_type) filter_bins.append((subdomain,)) # Construct list of energy group bounds tuples for all requested groups - if in_groups != 'all': + if not isinstance(in_groups, basestring): cv.check_iterable_type('groups', in_groups, Integral) for group in in_groups: filters.append('energy') filter_bins.append((self.energy_groups.get_group_bounds(group),)) # Construct list of energy group bounds tuples for all requested groups - if out_groups != 'all': + if not isinstance(out_groups, basestring): cv.check_iterable_type('groups', out_groups, Integral) for group in out_groups: filters.append('energyout') @@ -1887,7 +1887,7 @@ class ScatterMatrixXS(MGXS): """ # Construct a collection of the subdomains to report - if subdomains != 'all': + if not isinstance(subdomains, basestring): cv.check_iterable_type('subdomains', subdomains, Integral) elif self.domain_type == 'distribcell': subdomains = np.arange(self.num_subdomains, dtype=np.int) @@ -1926,12 +1926,6 @@ class ScatterMatrixXS(MGXS): bounds = self.energy_groups.get_group_bounds(group) string += template.format('', group, bounds[0], bounds[1]) - if subdomains == 'all': - if self.domain_type == 'distribcell': - subdomains = np.arange(self.num_subdomains, dtype=np.int) - else: - subdomains = [self.domain.id] - # Loop over all subdomains for subdomain in subdomains: @@ -2135,14 +2129,14 @@ class Chi(MGXS): filter_bins = [] # Construct a collection of the domain filter bins - if subdomains != 'all': + if not isinstance(subdomains, basestring): cv.check_iterable_type('subdomains', subdomains, Integral) for subdomain in subdomains: filters.append(self.domain_type) filter_bins.append((subdomain,)) # Construct list of energy group bounds tuples for all requested groups - if groups != 'all': + if not isinstance(groups, basestring): cv.check_iterable_type('groups', groups, Integral) for group in groups: filters.append('energyout') From 45495b300f3418d9fe79bf9aac7527a0bba27559 Mon Sep 17 00:00:00 2001 From: "wbinventor@gmail.com" Date: Wed, 27 Jan 2016 16:44:52 -0500 Subject: [PATCH 07/24] Fixed issues with typechecking for tally aggregation --- openmc/aggregate.py | 409 ------------------------------------------ openmc/cross.py | 422 +++++++++++++++++++++++++++++++++++++++++++- openmc/tallies.py | 11 +- 3 files changed, 419 insertions(+), 423 deletions(-) delete mode 100644 openmc/aggregate.py diff --git a/openmc/aggregate.py b/openmc/aggregate.py deleted file mode 100644 index 011ad38506..0000000000 --- a/openmc/aggregate.py +++ /dev/null @@ -1,409 +0,0 @@ -import sys -from numbers import Integral - -import numpy as np - -from openmc import Filter, Nuclide -from openmc.cross import CrossScore, CrossNuclide, CrossFilter -from openmc.filter import _FILTER_TYPES -import openmc.checkvalue as cv - - -if sys.version_info[0] >= 3: - basestring = str - -# Acceptable tally aggregation operations -_TALLY_AGGREGATE_OPS = ['sum', 'mean'] - - -class AggregateScore(object): - """A special-purpose tally score used to encapsulate an aggregate of a - subset or all of tally's scores for tally aggregation. - - Parameters - ---------- - scores : Iterable of str or CrossScore - The scores included in the aggregation - aggregate_op : str - The tally aggregation operator (e.g., 'sum', 'mean', etc.) used - to aggregate across a tally's scores with this AggregateScore - - Attributes - ---------- - scores : Iterable of str or CrossScore - The scores included in the aggregation - aggregate_op : str - The tally aggregation operator (e.g., 'sum', 'mean', etc.) used - to aggregate across a tally's scores with this AggregateScore - - """ - - def __init__(self, scores=None, aggregate_op=None): - - self._scores = None - self._aggregate_op = None - - if scores is not None: - self.scores = scores - if aggregate_op is not None: - self.aggregate_op = aggregate_op - - def __hash__(self): - return hash(repr(self)) - - def __eq__(self, other): - return str(other) == str(self) - - def __ne__(self, other): - return not self == other - - def __deepcopy__(self, memo): - existing = memo.get(id(self)) - - # If this is the first time we have tried to copy this object, create a copy - if existing is None: - clone = type(self).__new__(type(self)) - clone._scores = self.scores - clone._aggregate_op = self.aggregate_op - - memo[id(self)] = clone - - return clone - - # If this object has been copied before, return the first copy made - else: - return existing - - def __repr__(self): - string = ', '.join(map(str, self.scores)) - string = '{0}({1})'.format(self.aggregate_op, string) - return string - - @property - def scores(self): - return self._scores - - @property - def aggregate_op(self): - return self._aggregate_op - - @scores.setter - def scores(self, scores): - cv.check_iterable_type('scores', scores, basestring) - self._scores = scores - - @aggregate_op.setter - def aggregate_op(self, aggregate_op): - cv.check_type('aggregate_op', aggregate_op, (basestring, CrossScore)) - cv.check_value('aggregate_op', aggregate_op, _TALLY_AGGREGATE_OPS) - self._aggregate_op = aggregate_op - - -class AggregateNuclide(object): - """A special-purpose tally nuclide used to encapsulate an aggregate of a - subset or all of tally's nuclides for tally aggregation. - - Parameters - ---------- - nuclides : Iterable of str or Nuclide or CrossNuclide - The nuclides included in the aggregation - aggregate_op : str - The tally aggregation operator (e.g., 'sum', 'mean', etc.) used - to aggregate across a tally's nuclides with this AggregateNuclide - - Attributes - ---------- - nuclides : Iterable of str or Nuclide or CrossNuclide - The nuclides included in the aggregation - aggregate_op : str - The tally aggregation operator (e.g., 'sum', 'mean', etc.) used - to aggregate across a tally's nuclides with this AggregateNuclide - - """ - - def __init__(self, nuclides=None, aggregate_op=None): - - self._nuclides = None - self._aggregate_op = None - - if nuclides is not None: - self.nuclides = nuclides - if aggregate_op is not None: - self.aggregate_op = aggregate_op - - def __hash__(self): - return hash(repr(self)) - - def __eq__(self, other): - return str(other) == str(self) - - def __ne__(self, other): - return not self == other - - def __deepcopy__(self, memo): - existing = memo.get(id(self)) - - # If this is the first time we have tried to copy this object, create a copy - if existing is None: - clone = type(self).__new__(type(self)) - clone._nuclides = self.nuclides - clone._aggregate_op = self._aggregate_op - - memo[id(self)] = clone - - return clone - - # If this object has been copied before, return the first copy made - else: - return existing - - def __repr__(self): - - # Append each nuclide in the aggregate to the string - string = '{0}('.format(self.aggregate_op) - names = [nuclide.name if isinstance(nuclide, Nuclide) else str(nuclide) - for nuclide in self.nuclides] - string += ', '.join(map(str, names)) + ')' - return string - - @property - def nuclides(self): - return self._nuclides - - @property - def aggregate_op(self): - return self._aggregate_op - - @nuclides.setter - def nuclides(self, nuclides): - cv.check_iterable_type('nuclides', nuclides, - (basestring, Nuclide, CrossNuclide)) - self._nuclides = nuclides - - @aggregate_op.setter - def aggregate_op(self, aggregate_op): - cv.check_type('aggregate_op', aggregate_op, basestring) - cv.check_value('aggregate_op', aggregate_op, _TALLY_AGGREGATE_OPS) - self._aggregate_op = aggregate_op - - -class AggregateFilter(object): - """A special-purpose tally filter used to encapsulate an aggregate of a - subset or all of a tally filter's bins for tally aggregation. - - Parameters - ---------- - aggregate_filter : Filter or CrossFilter - The filter included in the aggregation - bins : Iterable of tuple - The filter bins included in the aggregation - aggregate_op : str - The tally aggregation operator (e.g., 'sum', 'mean', etc.) used - to aggregate across a tally filter's bins with this AggregateFilter - - Attributes - ---------- - type : str - The type of the aggregatefilter (e.g., 'sum(energy)', 'sum(cell)') - aggregate_filter : filter - The filter included in the aggregation - aggregate_op : str - The tally aggregation operator (e.g., 'sum', 'mean', etc.) used - to aggregate across a tally filter's bins with this AggregateFilter - bins : Iterable of tuple - The filter bins included in the aggregation - num_bins : Integral - The number of filter bins (always 1 if aggregate_filter is defined) - stride : Integral - The number of filter, nuclide and score bins within each of this - aggregatefilter's bins. - - """ - - def __init__(self, aggregate_filter=None, bins=None, aggregate_op=None): - - self._type = '{0}({1})'.format(aggregate_op, aggregate_filter.type) - self._bins = None - self._stride = None - - self._aggregate_filter = None - self._aggregate_op = None - - if aggregate_filter is not None: - self.aggregate_filter = aggregate_filter - if bins is not None: - self.bins = bins - if aggregate_op is not None: - self.aggregate_op = aggregate_op - - def __hash__(self): - return hash(repr(self)) - - def __eq__(self, other): - return str(other) == str(self) - - def __ne__(self, other): - return not self == other - - def __repr__(self): - string = 'AggregateFilter\n' - string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self.type) - string += '{0: <16}{1}{2}\n'.format('\tBins', '=\t', self.bins) - return string - - def __deepcopy__(self, memo): - existing = memo.get(id(self)) - - # If this is the first time we have tried to copy this object, create a copy - if existing is None: - clone = type(self).__new__(type(self)) - clone._type = self.type - clone._aggregate_filter = self.aggregate_filter - clone._aggregate_op = self.aggregate_op - clone._bins = self._bins - clone._stride = self.stride - - memo[id(self)] = clone - - return clone - - # If this object has been copied before, return the first copy made - else: - return existing - - @property - def aggregate_filter(self): - return self._aggregate_filter - - @property - def aggregate_op(self): - return self._aggregate_op - - @property - def type(self): - return self._type - - @property - def bins(self): - return self._bins - - @property - def num_bins(self): - return 1 if self.aggregate_filter else 0 - - @property - def stride(self): - return self._stride - - @type.setter - def type(self, filter_type): - if filter_type not in _FILTER_TYPES.values(): - msg = 'Unable to set AggregateFilter type to "{0}" since it ' \ - 'is not one of the supported types'.format(filter_type) - raise ValueError(msg) - - self._type = filter_type - - @aggregate_filter.setter - def aggregate_filter(self, aggregate_filter): - cv.check_type('aggregate_filter', aggregate_filter, (Filter, CrossFilter)) - self._aggregate_filter = aggregate_filter - - @bins.setter - def bins(self, bins): - cv.check_iterable_type('bins', bins, (Integral, tuple)) - self._bins = bins - - @aggregate_op.setter - def aggregate_op(self, aggregate_op): - cv.check_type('aggregate_op', aggregate_op, basestring) - cv.check_value('aggregate_op', aggregate_op, _TALLY_AGGREGATE_OPS) - self._aggregate_op = aggregate_op - - @stride.setter - def stride(self, stride): - self._stride = stride - - def get_bin_index(self, filter_bin): - """Returns the index in the AggregateFilter for some bin. - - Parameters - ---------- - filter_bin : Integral or tuple of Real - A tuple of value(s) corresponding to the bin of interest in - the aggregated filter. The bin is the integer ID for 'material', - 'surface', 'cell', 'cellborn', and 'universe' Filters. The bin - is the integer cell instance ID for 'distribcell' Filters. The - bin is a 2-tuple of floats for 'energy' and 'energyout' filters - corresponding to the energy boundaries of the bin of interest. - The bin is a (x,y,z) 3-tuple for 'mesh' filters corresponding to - the mesh cell of interest. - - Returns - ------- - filter_index : Integral - The index in the Tally data array for this filter bin. For an - AggregateTally the filter bin index is always unity. - - Raises - ------ - ValueError - When the filter_bin is not part of the aggregated filter's bins - - """ - - if filter_bin not in self.bins: - msg = 'Unable to get the bin index for AggregateFilter since ' \ - '"{0}" is not one of the bins'.format(filter_bin) - raise ValueError(msg) - else: - return 0 - - def get_pandas_dataframe(self, datasize, summary=None): - """Builds a Pandas DataFrame for the AggregateFilter's bins. - - This method constructs a Pandas DataFrame object for the AggregateFilter - with columns annotated by filter bin information. This is a helper - method for the Tally.get_pandas_dataframe(...) method. - - Parameters - ---------- - datasize : Integral - The total number of bins in the tally corresponding to this filter - summary : None or Summary - An optional Summary object to be used to construct columns for - distribcell tally filters (default is None). NOTE: This parameter - is not used by the AggregateFilter and simply mirrors the method - signature for the CrossFilter. - - Returns - ------- - pandas.DataFrame - A Pandas DataFrame with columns of strings that characterize the - aggregatefilter's bins. Each entry in the DataFrame will include - one or more aggregation operations used to construct the - aggregatefilter's bins. The number of rows in the DataFrame is the - same as the total number of bins in the corresponding tally, with - the filter bins appropriately tiled to map to the corresponding - tally bins. - - See also - -------- - Tally.get_pandas_dataframe(), Filter.get_pandas_dataframe(), - CrossFilter.get_pandas_dataframe() - - """ - - import pandas as pd - - # Construct a sring representing the filter aggregation - aggregate_bin = '{0}('.format(self.aggregate_op) - aggregate_bin += ', '.join(map(str, self.bins)) + ')' - - # Construct NumPy array of bin repeated for each element in dataframe - aggregate_bin_array = np.array([aggregate_bin]) - aggregate_bin_array = np.repeat(aggregate_bin_array, datasize) - - # Construct Pandas DataFrame for the AggregateFilter - df = pd.DataFrame({self.type: aggregate_bin_array}) - return df diff --git a/openmc/cross.py b/openmc/cross.py index ee0fcb4c82..65e12c5d27 100644 --- a/openmc/cross.py +++ b/openmc/cross.py @@ -1,16 +1,21 @@ import sys +from numbers import Integral + +import numpy as np from openmc import Filter, Nuclide from openmc.filter import _FILTER_TYPES import openmc.checkvalue as cv - if sys.version_info[0] >= 3: basestring = str # Acceptable tally arithmetic binary operations _TALLY_ARITHMETIC_OPS = ['+', '-', '*', '/', '^'] +# Acceptable tally aggregation operations +_TALLY_AGGREGATE_OPS = ['sum', 'mean'] + class CrossScore(object): """A special-purpose tally score used to encapsulate all combinations of two @@ -97,17 +102,19 @@ class CrossScore(object): @left_score.setter def left_score(self, left_score): - cv.check_type('left_score', left_score, (basestring, CrossScore)) + cv.check_type('left_score', left_score, + (basestring, CrossScore, AggregateScore)) self._left_score = left_score @right_score.setter def right_score(self, right_score): - cv.check_type('right_score', right_score, (basestring, CrossScore)) + cv.check_type('right_score', right_score, + (basestring, CrossScore, AggregateScore)) self._right_score = right_score @binary_op.setter def binary_op(self, binary_op): - cv.check_type('binary_op', binary_op, (basestring, CrossScore)) + cv.check_type('binary_op', binary_op, basestring) cv.check_value('binary_op', binary_op, _TALLY_ARITHMETIC_OPS) self._binary_op = binary_op @@ -214,12 +221,14 @@ class CrossNuclide(object): @left_nuclide.setter def left_nuclide(self, left_nuclide): - cv.check_type('left_nuclide', left_nuclide, (Nuclide, CrossNuclide)) + cv.check_type('left_nuclide', left_nuclide, + (Nuclide, CrossNuclide, AggregateNuclide)) self._left_nuclide = left_nuclide @right_nuclide.setter def right_nuclide(self, right_nuclide): - cv.check_type('right_nuclide', right_nuclide, (Nuclide, CrossNuclide)) + cv.check_type('right_nuclide', right_nuclide, + (Nuclide, CrossNuclide, AggregateNuclide)) self._right_nuclide = right_nuclide @binary_op.setter @@ -372,13 +381,15 @@ class CrossFilter(object): @left_filter.setter def left_filter(self, left_filter): - cv.check_type('left_filter', left_filter, (Filter, CrossFilter)) + cv.check_type('left_filter', left_filter, + (Filter, CrossFilter, AggregateFilter)) self._left_filter = left_filter self._bins['left'] = left_filter.bins @right_filter.setter def right_filter(self, right_filter): - cv.check_type('right_filter', right_filter, (Filter, CrossFilter)) + cv.check_type('right_filter', right_filter, + (Filter, CrossFilter, AggregateFilter)) self._right_filter = right_filter self._bins['right'] = right_filter.bins @@ -472,3 +483,398 @@ class CrossFilter(object): df = '(' + left_df + ' ' + self.binary_op + ' ' + right_df + ')' return df + + +class AggregateScore(object): + """A special-purpose tally score used to encapsulate an aggregate of a + subset or all of tally's scores for tally aggregation. + + Parameters + ---------- + scores : Iterable of str or CrossScore + The scores included in the aggregation + aggregate_op : str + The tally aggregation operator (e.g., 'sum', 'mean', etc.) used + to aggregate across a tally's scores with this AggregateScore + + Attributes + ---------- + scores : Iterable of str or CrossScore + The scores included in the aggregation + aggregate_op : str + The tally aggregation operator (e.g., 'sum', 'mean', etc.) used + to aggregate across a tally's scores with this AggregateScore + + """ + + def __init__(self, scores=None, aggregate_op=None): + + self._scores = None + self._aggregate_op = None + + if scores is not None: + self.scores = scores + if aggregate_op is not None: + self.aggregate_op = aggregate_op + + def __hash__(self): + return hash(repr(self)) + + def __eq__(self, other): + return str(other) == str(self) + + def __ne__(self, other): + return not self == other + + def __deepcopy__(self, memo): + existing = memo.get(id(self)) + + # If this is the first time we have tried to copy this object, create a copy + if existing is None: + clone = type(self).__new__(type(self)) + clone._scores = self.scores + clone._aggregate_op = self.aggregate_op + + memo[id(self)] = clone + + return clone + + # If this object has been copied before, return the first copy made + else: + return existing + + def __repr__(self): + string = ', '.join(map(str, self.scores)) + string = '{0}({1})'.format(self.aggregate_op, string) + return string + + @property + def scores(self): + return self._scores + + @property + def aggregate_op(self): + return self._aggregate_op + + @scores.setter + def scores(self, scores): + cv.check_iterable_type('scores', scores, + (basestring, CrossScore, AggregateScore)) + self._scores = scores + + @aggregate_op.setter + def aggregate_op(self, aggregate_op): + cv.check_type('aggregate_op', aggregate_op, (basestring, CrossScore)) + cv.check_value('aggregate_op', aggregate_op, _TALLY_AGGREGATE_OPS) + self._aggregate_op = aggregate_op + + +class AggregateNuclide(object): + """A special-purpose tally nuclide used to encapsulate an aggregate of a + subset or all of tally's nuclides for tally aggregation. + + Parameters + ---------- + nuclides : Iterable of str or Nuclide or CrossNuclide + The nuclides included in the aggregation + aggregate_op : str + The tally aggregation operator (e.g., 'sum', 'mean', etc.) used + to aggregate across a tally's nuclides with this AggregateNuclide + + Attributes + ---------- + nuclides : Iterable of str or Nuclide or CrossNuclide + The nuclides included in the aggregation + aggregate_op : str + The tally aggregation operator (e.g., 'sum', 'mean', etc.) used + to aggregate across a tally's nuclides with this AggregateNuclide + + """ + + def __init__(self, nuclides=None, aggregate_op=None): + + self._nuclides = None + self._aggregate_op = None + + if nuclides is not None: + self.nuclides = nuclides + if aggregate_op is not None: + self.aggregate_op = aggregate_op + + def __hash__(self): + return hash(repr(self)) + + def __eq__(self, other): + return str(other) == str(self) + + def __ne__(self, other): + return not self == other + + def __deepcopy__(self, memo): + existing = memo.get(id(self)) + + # If this is the first time we have tried to copy this object, create a copy + if existing is None: + clone = type(self).__new__(type(self)) + clone._nuclides = self.nuclides + clone._aggregate_op = self._aggregate_op + + memo[id(self)] = clone + + return clone + + # If this object has been copied before, return the first copy made + else: + return existing + + def __repr__(self): + + # Append each nuclide in the aggregate to the string + string = '{0}('.format(self.aggregate_op) + names = [nuclide.name if isinstance(nuclide, Nuclide) else str(nuclide) + for nuclide in self.nuclides] + string += ', '.join(map(str, names)) + ')' + return string + + @property + def nuclides(self): + return self._nuclides + + @property + def aggregate_op(self): + return self._aggregate_op + + @nuclides.setter + def nuclides(self, nuclides): + cv.check_iterable_type('nuclides', nuclides, + (basestring, Nuclide, CrossNuclide, AggregateNuclide)) + self._nuclides = nuclides + + @aggregate_op.setter + def aggregate_op(self, aggregate_op): + cv.check_type('aggregate_op', aggregate_op, basestring) + cv.check_value('aggregate_op', aggregate_op, _TALLY_AGGREGATE_OPS) + self._aggregate_op = aggregate_op + + +class AggregateFilter(object): + """A special-purpose tally filter used to encapsulate an aggregate of a + subset or all of a tally filter's bins for tally aggregation. + + Parameters + ---------- + aggregate_filter : Filter or CrossFilter + The filter included in the aggregation + bins : Iterable of tuple + The filter bins included in the aggregation + aggregate_op : str + The tally aggregation operator (e.g., 'sum', 'mean', etc.) used + to aggregate across a tally filter's bins with this AggregateFilter + + Attributes + ---------- + type : str + The type of the aggregatefilter (e.g., 'sum(energy)', 'sum(cell)') + aggregate_filter : filter + The filter included in the aggregation + aggregate_op : str + The tally aggregation operator (e.g., 'sum', 'mean', etc.) used + to aggregate across a tally filter's bins with this AggregateFilter + bins : Iterable of tuple + The filter bins included in the aggregation + num_bins : Integral + The number of filter bins (always 1 if aggregate_filter is defined) + stride : Integral + The number of filter, nuclide and score bins within each of this + aggregatefilter's bins. + + """ + + def __init__(self, aggregate_filter=None, bins=None, aggregate_op=None): + + self._type = '{0}({1})'.format(aggregate_op, aggregate_filter.type) + self._bins = None + self._stride = None + + self._aggregate_filter = None + self._aggregate_op = None + + if aggregate_filter is not None: + self.aggregate_filter = aggregate_filter + if bins is not None: + self.bins = bins + if aggregate_op is not None: + self.aggregate_op = aggregate_op + + def __hash__(self): + return hash(repr(self)) + + def __eq__(self, other): + return str(other) == str(self) + + def __ne__(self, other): + return not self == other + + def __repr__(self): + string = 'AggregateFilter\n' + string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self.type) + string += '{0: <16}{1}{2}\n'.format('\tBins', '=\t', self.bins) + return string + + def __deepcopy__(self, memo): + existing = memo.get(id(self)) + + # If this is the first time we have tried to copy this object, create a copy + if existing is None: + clone = type(self).__new__(type(self)) + clone._type = self.type + clone._aggregate_filter = self.aggregate_filter + clone._aggregate_op = self.aggregate_op + clone._bins = self._bins + clone._stride = self.stride + + memo[id(self)] = clone + + return clone + + # If this object has been copied before, return the first copy made + else: + return existing + + @property + def aggregate_filter(self): + return self._aggregate_filter + + @property + def aggregate_op(self): + return self._aggregate_op + + @property + def type(self): + return self._type + + @property + def bins(self): + return self._bins + + @property + def num_bins(self): + return 1 if self.aggregate_filter else 0 + + @property + def stride(self): + return self._stride + + @type.setter + def type(self, filter_type): + if filter_type not in _FILTER_TYPES.values(): + msg = 'Unable to set AggregateFilter type to "{0}" since it ' \ + 'is not one of the supported types'.format(filter_type) + raise ValueError(msg) + + self._type = filter_type + + @aggregate_filter.setter + def aggregate_filter(self, aggregate_filter): + cv.check_type('aggregate_filter', aggregate_filter, + (Filter, CrossFilter, AggregateFilter)) + self._aggregate_filter = aggregate_filter + + @bins.setter + def bins(self, bins): + cv.check_iterable_type('bins', bins, (Integral, tuple)) + self._bins = bins + + @aggregate_op.setter + def aggregate_op(self, aggregate_op): + cv.check_type('aggregate_op', aggregate_op, basestring) + cv.check_value('aggregate_op', aggregate_op, _TALLY_AGGREGATE_OPS) + self._aggregate_op = aggregate_op + + @stride.setter + def stride(self, stride): + self._stride = stride + + def get_bin_index(self, filter_bin): + """Returns the index in the AggregateFilter for some bin. + + Parameters + ---------- + filter_bin : Integral or tuple of Real + A tuple of value(s) corresponding to the bin of interest in + the aggregated filter. The bin is the integer ID for 'material', + 'surface', 'cell', 'cellborn', and 'universe' Filters. The bin + is the integer cell instance ID for 'distribcell' Filters. The + bin is a 2-tuple of floats for 'energy' and 'energyout' filters + corresponding to the energy boundaries of the bin of interest. + The bin is a (x,y,z) 3-tuple for 'mesh' filters corresponding to + the mesh cell of interest. + + Returns + ------- + filter_index : Integral + The index in the Tally data array for this filter bin. For an + AggregateTally the filter bin index is always unity. + + Raises + ------ + ValueError + When the filter_bin is not part of the aggregated filter's bins + + """ + + if filter_bin not in self.bins: + msg = 'Unable to get the bin index for AggregateFilter since ' \ + '"{0}" is not one of the bins'.format(filter_bin) + raise ValueError(msg) + else: + return 0 + + def get_pandas_dataframe(self, datasize, summary=None): + """Builds a Pandas DataFrame for the AggregateFilter's bins. + + This method constructs a Pandas DataFrame object for the AggregateFilter + with columns annotated by filter bin information. This is a helper + method for the Tally.get_pandas_dataframe(...) method. + + Parameters + ---------- + datasize : Integral + The total number of bins in the tally corresponding to this filter + summary : None or Summary + An optional Summary object to be used to construct columns for + distribcell tally filters (default is None). NOTE: This parameter + is not used by the AggregateFilter and simply mirrors the method + signature for the CrossFilter. + + Returns + ------- + pandas.DataFrame + A Pandas DataFrame with columns of strings that characterize the + aggregatefilter's bins. Each entry in the DataFrame will include + one or more aggregation operations used to construct the + aggregatefilter's bins. The number of rows in the DataFrame is the + same as the total number of bins in the corresponding tally, with + the filter bins appropriately tiled to map to the corresponding + tally bins. + + See also + -------- + Tally.get_pandas_dataframe(), Filter.get_pandas_dataframe(), + CrossFilter.get_pandas_dataframe() + + """ + + import pandas as pd + + # Construct a sring representing the filter aggregation + aggregate_bin = '{0}('.format(self.aggregate_op) + aggregate_bin += ', '.join(map(str, self.bins)) + ')' + + # Construct NumPy array of bin repeated for each element in dataframe + aggregate_bin_array = np.array([aggregate_bin]) + aggregate_bin_array = np.repeat(aggregate_bin_array, datasize) + + # Construct Pandas DataFrame for the AggregateFilter + df = pd.DataFrame({self.type: aggregate_bin_array}) + return df diff --git a/openmc/tallies.py b/openmc/tallies.py index 9b75f35d48..fb07532a0e 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -12,8 +12,7 @@ import sys import numpy as np from openmc import Mesh, Filter, Trigger, Nuclide -from openmc.cross import CrossScore, CrossNuclide, CrossFilter -from openmc.aggregate import AggregateScore, AggregateNuclide, AggregateFilter +from openmc.cross import * from openmc.filter import _FILTER_TYPES import openmc.checkvalue as cv from openmc.clean_xml import * @@ -2680,11 +2679,11 @@ class Tally(object): new_tally = copy.deepcopy(self) new_tally.sparse = False - if self.sum is not None: + if not self.derived and self.sum is not None: new_sum = self.get_values(scores, filters, filter_bins, nuclides, 'sum') new_tally.sum = new_sum - if self.sum_sq is not None: + if not self.derived and self.sum_sq is not None: new_sum_sq = self.get_values(scores, filters, filter_bins, nuclides, 'sum_sq') new_tally.sum_sq = new_sum_sq @@ -2955,10 +2954,10 @@ class Tally(object): diag_indices[start:end] = indices + (i * new_filter.num_bins**2) # Inject this Tally's data along the diagonal of the diagonalized Tally - if self.sum is not None: + if not self.derived and self.sum is not None: new_tally._sum = np.zeros(new_tally.shape, dtype=np.float64) new_tally._sum[diag_indices, :, :] = self.sum - if self.sum_sq is not None: + if not self.derived and self.sum_sq is not None: new_tally._sum_sq = np.zeros(new_tally.shape, dtype=np.float64) new_tally._sum_sq[diag_indices, :, :] = self.sum_sq if self.mean is not None: From bd841a268f86117da6e9e370ef99088f9ea416d6 Mon Sep 17 00:00:00 2001 From: "wbinventor@gmail.com" Date: Thu, 28 Jan 2016 12:56:52 -0500 Subject: [PATCH 08/24] Fixed bug in StatePoint.with_summary property --- openmc/statepoint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 49ac43590e..4c6f956a49 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -451,7 +451,7 @@ class StatePoint(object): @property def with_summary(self): - return False if self.summary is None else True + return False if self.summary is False else True @sparse.setter def sparse(self, sparse): From 3d9353b086076cce4f0a95ee19d1b028c1c41c18 Mon Sep 17 00:00:00 2001 From: "wbinventor@gmail.com" Date: Thu, 28 Jan 2016 13:41:08 -0500 Subject: [PATCH 09/24] Removed StatePoint.with_summary property --- openmc/mgxs/library.py | 2 +- openmc/mgxs/mgxs.py | 2 +- openmc/statepoint.py | 6 +----- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/openmc/mgxs/library.py b/openmc/mgxs/library.py index ca9fa5d669..4b8d8a9149 100644 --- a/openmc/mgxs/library.py +++ b/openmc/mgxs/library.py @@ -396,7 +396,7 @@ class Library(object): cv.check_type('statepoint', statepoint, openmc.StatePoint) - if not statepoint.with_summary: + if statepoint.summary is None: msg = 'Unable to load data from a statepoint which has not been ' \ 'linked with a summary file' raise ValueError(msg) diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index bfa8b02c5c..d1f3d4b069 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -583,7 +583,7 @@ class MGXS(object): cv.check_type('statepoint', statepoint, openmc.statepoint.StatePoint) - if not statepoint.with_summary: + if statepoint.summary is None: msg = 'Unable to load data from a statepoint which has not been ' \ 'linked with a summary file' raise ValueError(msg) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 4c6f956a49..b7af1a9618 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -1,4 +1,4 @@ -import sys +mport sys import re import numpy as np @@ -449,10 +449,6 @@ class StatePoint(object): def summary(self): return self._summary - @property - def with_summary(self): - return False if self.summary is False else True - @sparse.setter def sparse(self, sparse): """Convert tally data from NumPy arrays to SciPy list of lists (LIL) From 1e89fd53e6b5536b53ed23e2482a92a6e5fdcbff Mon Sep 17 00:00:00 2001 From: "wbinventor@gmail.com" Date: Thu, 28 Jan 2016 13:50:11 -0500 Subject: [PATCH 10/24] Fixed typo in imports for statepoint.py --- openmc/statepoint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index b7af1a9618..f5b5b2e72d 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -1,4 +1,4 @@ -mport sys +import sys import re import numpy as np From 3cbea749cb7919a826bcc73f5fe1edbddcc2e497 Mon Sep 17 00:00:00 2001 From: "wbinventor@gmail.com" Date: Thu, 28 Jan 2016 13:54:38 -0500 Subject: [PATCH 11/24] Now clear any old tallies in MGXS.load_from_statepoint(...) --- openmc/mgxs/mgxs.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index d1f3d4b069..f241274581 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -612,6 +612,11 @@ class MGXS(object): filters = [] filter_bins = [] + # Clear any tallies previously loaded from a statepoint + self._tallies = None + self._xs_tally = None + self._rxn_rate_tally = None + # Find, slice and store Tallies from StatePoint # The tally slicing is needed if tally merging was used for tally_type, tally in self.tallies.items(): From 6cafdd5b65c074ad02f25d1fe286f61d79354e56 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 28 Jan 2016 13:38:02 -0600 Subject: [PATCH 12/24] Reorganize score tables as per suggestions by @wbinventor --- docs/source/usersguide/input.rst | 364 ++++++++++++++----------------- 1 file changed, 167 insertions(+), 197 deletions(-) diff --git a/docs/source/usersguide/input.rst b/docs/source/usersguide/input.rst index ca16c8fef6..a9dda8ff47 100644 --- a/docs/source/usersguide/input.rst +++ b/docs/source/usersguide/input.rst @@ -1476,36 +1476,186 @@ The ```` element accepts the following sub-elements: :scores: A space-separated list of the desired responses to be accumulated. The accepted - options are listed in the following table: + options are listed in the following tables: - .. table:: Score types available in OpenMC + .. table:: **Flux scores: units are particle-cm per source particle.** +----------------------+---------------------------------------------------+ |Score | Description | +======================+===================================================+ - |flux |Total flux in particle-cm per source particle. | - | | | + |flux |Total flux. | +----------------------+---------------------------------------------------+ - |total |Total reaction rate in reactions per source | - | |particle. | + |flux-YN |Spherical harmonic expansion of the direction of | + | |motion :math:`\left(\Omega\right)` of the total | + | |flux. This score will tally all of the harmonic | + | |moments of order 0 to N. N must be between 0 and | + | |10. | + +----------------------+---------------------------------------------------+ + + .. table:: **Reaction scores: units are reactions per source particle.** + + +----------------------+---------------------------------------------------+ + |Score | Description | + +======================+===================================================+ + |absorption |Total absorption rate. This accounts for all | + | |reactions which do not produce secondary neutrons. | + +----------------------+---------------------------------------------------+ + |elastic |Elastic scattering reaction rate. | + +----------------------+---------------------------------------------------+ + |fission |Total fission reaction rate. | +----------------------+---------------------------------------------------+ |scatter |Total scattering rate. Can also be identified with | - | |the "scatter-0" response type. Units are reactions | - | |per source particle. | + | |the "scatter-0" response type. | +----------------------+---------------------------------------------------+ - |absorption |Total absorption rate. This accounts for all | - | |reactions which do not produce secondary | - | |neutrons. Units are reactions per source particle. | + |scatter-N |Tally the N\ :sup:`th` \ scattering moment, where N| + | |is the Legendre expansion order of the change in | + | |particle angle :math:`\left(\mu\right)`. N must be | + | |between 0 and 10. As an example, tallying the 2\ | + | |:sup:`nd` \ scattering moment would be specified as| + | |``scatter-2``. | +----------------------+---------------------------------------------------+ - |fission |Total fission rate in reactions per source | - | |particle. | + |scatter-PN |Tally all of the scattering moments from order 0 to| + | |N, where N is the Legendre expansion order of the | + | |change in particle angle | + | |:math:`\left(\mu\right)`. That is, "scatter-P1" is | + | |equivalent to requesting tallies of "scatter-0" and| + | |"scatter-1". Like for "scatter-N", N must be | + | |between 0 and 10. As an example, tallying up to the| + | |2\ :sup:`nd` \ scattering moment would be specified| + | |as `` scatter-P2 ``. | +----------------------+---------------------------------------------------+ - |nu-fission |Total production of neutrons due to fission. Units | - | |are neutrons produced per source neutron. | + |scatter-YN |"scatter-YN" is similar to "scatter-PN" except an | + | |additional expansion is performed for the incoming | + | |particle direction :math:`\left(\Omega\right)` | + | |using the real spherical harmonics. This is useful| + | |for performing angular flux moment weighting of the| + | |scattering moments. Like "scatter-PN", "scatter-YN"| + | |will tally all of the moments from order 0 to N; N | + | |again must be between 0 and 10. | +----------------------+---------------------------------------------------+ + |total |Total reaction rate. | + +----------------------+---------------------------------------------------+ + |total-YN |The total reaction rate expanded via spherical | + | |harmonics about the direction of motion of the | + | |neutron, :math:`\Omega`. This score will tally all | + | |of the harmonic moments of order 0 to N. N must be| + | |between 0 and 10. | + +----------------------+---------------------------------------------------+ + |(n,2nd) |(n,2nd) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,2n) |(n,2n) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,3n) |(n,3n) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,na) |(n,n\ :math:`\alpha`\ ) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,n3a) |(n,n3\ :math:`\alpha`\ ) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,2na) |(n,2n\ :math:`\alpha`\ ) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,3na) |(n,3n\ :math:`\alpha`\ ) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,np) |(n,np) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,n2a) |(n,n2\ :math:`\alpha`\ ) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,2n2a) |(n,2n2\ :math:`\alpha`\ ) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,nd) |(n,nd) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,nt) |(n,nt) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,nHe-3) |(n,n\ :sup:`3`\ He) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,nd2a) |(n,nd2\ :math:`\alpha`\ ) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,nt2a) |(n,nt2\ :math:`\alpha`\ ) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,4n) |(n,4n) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,2np) |(n,2np) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,3np) |(n,3np) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,n2p) |(n,n2p) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,n*X*) |Level inelastic scattering reaction rate. The *X* | + | |indicates what which inelastic level, e.g., (n,n3) | + | |is third-level inelastic scattering. | + +----------------------+---------------------------------------------------+ + |(n,nc) |Continuum level inelastic scattering reaction rate.| + +----------------------+---------------------------------------------------+ + |(n,gamma) |Radiative capture reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,p) |(n,p) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,d) |(n,d) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,t) |(n,t) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,3He) |(n,\ :sup:`3`\ He) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,a) |(n,\ :math:`\alpha`\ ) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,2a) |(n,2\ :math:`\alpha`\ ) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,3a) |(n,3\ :math:`\alpha`\ ) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,2p) |(n,2p) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,pa) |(n,p\ :math:`\alpha`\ ) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,t2a) |(n,t2\ :math:`\alpha`\ ) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,d2a) |(n,d2\ :math:`\alpha`\ ) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,pd) |(n,pd) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,pt) |(n,pt) reaction rate. | + +----------------------+---------------------------------------------------+ + |(n,da) |(n,d\ :math:`\alpha`\ ) reaction rate. | + +----------------------+---------------------------------------------------+ + |*Arbitrary integer* |An arbitrary integer is interpreted to mean the | + | |reaction rate for a reaction with a given ENDF MT | + | |number. | + +----------------------+---------------------------------------------------+ + + .. table:: **Particle production scores: units are particles produced per + source particles.** + + +----------------------+---------------------------------------------------+ + |Score | Description | + +======================+===================================================+ |delayed-nu-fission |Total production of delayed neutrons due to | - | |fission. Units are neutrons produced per source | - | |neutron. | + | |fission. | + +----------------------+---------------------------------------------------+ + |nu-fission |Total production of neutrons due to fission. | + +----------------------+---------------------------------------------------+ + |nu-scatter, |These scores are similar in functionality to their | + |nu-scatter-N, |``scatter*`` equivalents except the total | + |nu-scatter-PN, |production of neutrons due to scattering is scored | + |nu-scatter-YN |vice simply the scattering rate. This accounts for | + | |multiplicity from (n,2n), (n,3n), and (n,4n) | + | |reactions. | + +----------------------+---------------------------------------------------+ + + .. table:: **Miscellaneous scores: units are indicated for each.** + + +----------------------+---------------------------------------------------+ + |Score | Description | + +======================+===================================================+ + |current |Partial currents on the boundaries of each cell in | + | |a mesh. Units are particles per source | + | |particle. Note that this score can only be used if | + | |a mesh filter has been specified. Furthermore, it | + | |may not be used in conjunction with any other | + | |score. | + +----------------------+---------------------------------------------------+ + |events |Number of scoring events. Units are events per | + | |source particle. | + +----------------------+---------------------------------------------------+ + |inverse-velocity |The flux-weighted inverse velocity where the | + | |velocity is in units of centimeters per second. | +----------------------+---------------------------------------------------+ |kappa-fission |The recoverable energy production rate due to | | |fission. The recoverable energy is defined as the | @@ -1518,186 +1668,6 @@ The ```` element accepts the following sub-elements: | |:math:`\gamma`-rays are assumed to deposit their | | |energy locally. Units are MeV per source particle. | +----------------------+---------------------------------------------------+ - |scatter-N |Tally the N\ :sup:`th` \ scattering moment, where N| - | |is the Legendre expansion order of the change in | - | |particle angle :math:`\left(\mu\right)`. N must be | - | |between 0 and 10. As an example, tallying the 2\ | - | |:sup:`nd` \ scattering moment would be specified as| - | |``scatter-2``. Units are reactions| - | |per source particle. | - +----------------------+---------------------------------------------------+ - |scatter-PN |Tally all of the scattering moments from order 0 to| - | |N, where N is the Legendre expansion order of the | - | |change in particle angle | - | |:math:`\left(\mu\right)`. That is, "scatter-P1" is | - | |equivalent to requesting tallies of "scatter-0" and| - | |"scatter-1". Like for "scatter-N", N must be | - | |between 0 and 10. As an example, tallying up to the| - | |2\ :sup:`nd` \ scattering moment would be specified| - | |as `` scatter-P2 ``. Units are | - | |reactions per source particle. | - +----------------------+---------------------------------------------------+ - |scatter-YN |"scatter-YN" is similar to "scatter-PN" except an | - | |additional expansion is performed for the incoming | - | |particle direction :math:`\left(\Omega\right)` | - | |using the real spherical harmonics. This is useful| - | |for performing angular flux moment weighting of the| - | |scattering moments. Like "scatter-PN", "scatter-YN"| - | |will tally all of the moments from order 0 to N; N | - | |again must be between 0 and 10. Units are reactions| - | |per source particle. | - +----------------------+---------------------------------------------------+ - |nu-scatter, |These scores are similar in functionality to their | - |nu-scatter-N, |``scatter*`` equivalents except the total | - |nu-scatter-PN, |production of neutrons due to scattering is scored | - |nu-scatter-YN |vice simply the scattering rate. This accounts for | - | |multiplicity from (n,2n), (n,3n), and (n,4n) | - | |reactions. Units are neutrons produced per source | - | |particle. | - +----------------------+---------------------------------------------------+ - |flux-YN |Spherical harmonic expansion of the direction of | - | |motion :math:`\left(\Omega\right)` of the total | - | |flux. This score will tally all of the harmonic | - | |moments of order 0 to N. N must be between 0 and | - | |10. Units are particle-cm per source particle. | - +----------------------+---------------------------------------------------+ - |total-YN |The total reaction rate expanded via spherical | - | |harmonics about the direction of motion of the | - | |neutron, :math:`\Omega`. This score will tally all | - | |of the harmonic moments of order 0 to N. N must be| - | |between 0 and 10. Units are reactions per source | - | |particle. | - +----------------------+---------------------------------------------------+ - |current |Partial currents on the boundaries of each cell in | - | |a mesh. Units are particles per source | - | |particle. Note that this score can only be used if | - | |a mesh filter has been specified. Furthermore, it | - | |may not be used in conjunction with any other | - | |score. | - +----------------------+---------------------------------------------------+ - |inverse-velocity |The flux-weighted inverse velocity where the | - | |velocity is in units of centimeters per second. | - +----------------------+---------------------------------------------------+ - |events |Number of scoring events. Units are events per | - | |source particle. | - +----------------------+---------------------------------------------------+ - |elastic |Elastic scattering reaction rate. Units are | - | |reactions per source particle. | - +----------------------+---------------------------------------------------+ - |(n,2nd) |(n,2nd) reaction rate. Units are reactions per | - | |source particle. | - +----------------------+---------------------------------------------------+ - |(n,2n) |(n,2n) reaction rate. Units are reactions per | - | |source particle. | - +----------------------+---------------------------------------------------+ - |(n,3n) |(n,3n) reaction rate. Units are reactions per | - | |source particle. | - +----------------------+---------------------------------------------------+ - |(n,na) |(n,n\ :math:`\alpha`\ ) reaction rate. Units are | - | |reactions per source particle. | - +----------------------+---------------------------------------------------+ - |(n,n3a) |(n,n3\ :math:`\alpha`\ ) reaction rate. Units are | - | |reactions per source particle. | - +----------------------+---------------------------------------------------+ - |(n,2na) |(n,2n\ :math:`\alpha`\ ) reaction rate. Units are | - | |reactions per source particle. | - +----------------------+---------------------------------------------------+ - |(n,3na) |(n,3n\ :math:`\alpha`\ ) reaction rate. Units are | - | |reactions per source particle. | - +----------------------+---------------------------------------------------+ - |(n,np) |(n,np) reaction rate. Units are reactions per | - | |source particle. | - +----------------------+---------------------------------------------------+ - |(n,n2a) |(n,n2\ :math:`\alpha`\ ) reaction rate. Units are | - | |reactions per source particle. | - +----------------------+---------------------------------------------------+ - |(n,2n2a) |(n,2n2\ :math:`\alpha`\ ) reaction rate. Units are | - | |reactions per source particle. | - +----------------------+---------------------------------------------------+ - |(n,nd) |(n,nd) reaction rate. Units are reactions per | - | |source particle. | - +----------------------+---------------------------------------------------+ - |(n,nt) |(n,nt) reaction rate. Units are reactions per | - | |source particle. | - +----------------------+---------------------------------------------------+ - |(n,nHe-3) |(n,n\ :sup:`3`\ He) reaction rate. Units are | - | |reactions per source particle. | - +----------------------+---------------------------------------------------+ - |(n,nd2a) |(n,nd2\ :math:`\alpha`\ ) reaction rate. Units are | - | |reactions per source particle. | - +----------------------+---------------------------------------------------+ - |(n,nt2a) |(n,nt2\ :math:`\alpha`\ ) reaction rate. Units are | - | |reactions per source particle. | - +----------------------+---------------------------------------------------+ - |(n,4n) |(n,4n) reaction rate. Units are reactions per | - | |source particle. | - +----------------------+---------------------------------------------------+ - |(n,2np) |(n,2np) reaction rate. Units are reactions per | - | |source particle. | - +----------------------+---------------------------------------------------+ - |(n,3np) |(n,3np) reaction rate. Units are reactions per | - | |source particle. | - +----------------------+---------------------------------------------------+ - |(n,n2p) |(n,n2p) reaction rate. Units are reactions per | - | |source particle. | - +----------------------+---------------------------------------------------+ - |(n,n*X*) |Level inelastic scattering reaction rate. The *X* | - | |indicates what which inelastic level, e.g., (n,n3) | - | |is third-level inelastic scattering. Units are | - | |reactions per source particle. | - +----------------------+---------------------------------------------------+ - |(n,nc) |Continuum level inelastic scattering reaction | - | |rate. Units are reactions per source particle. | - +----------------------+---------------------------------------------------+ - |(n,gamma) |Radiative capture reaction rate. Units are | - | |reactions per source particle. | - +----------------------+---------------------------------------------------+ - |(n,p) |(n,p) reaction rate. Units are reactions per source| - | |particle. | - +----------------------+---------------------------------------------------+ - |(n,d) |(n,d) reaction rate. Units are reactions per source| - | |particle. | - +----------------------+---------------------------------------------------+ - |(n,t) |(n,t) reaction rate. Units are reactions per source| - | |particle. | - +----------------------+---------------------------------------------------+ - |(n,3He) |(n,\ :sup:`3`\ He) reaction rate. Units are | - | |reactions per source particle. | - +----------------------+---------------------------------------------------+ - |(n,a) |(n,\ :math:`\alpha`\ ) reaction rate. Units are | - | |reactions per source particle. | - +----------------------+---------------------------------------------------+ - |(n,2a) |(n,2\ :math:`\alpha`\ ) reaction rate. Units are | - | |reactions per source particle. | - +----------------------+---------------------------------------------------+ - |(n,3a) |(n,3\ :math:`\alpha`\ ) reaction rate. Units are | - | |reactions per source particle. | - +----------------------+---------------------------------------------------+ - |(n,2p) |(n,2p) reaction rate. Units are reactions per | - | |source particle. | - +----------------------+---------------------------------------------------+ - |(n,pa) |(n,p\ :math:`\alpha`\ ) reaction rate. Units are | - | |reactions per source particle. | - +----------------------+---------------------------------------------------+ - |(n,t2a) |(n,t2\ :math:`\alpha`\ ) reaction rate. Units are | - | |reactions per source particle. | - +----------------------+---------------------------------------------------+ - |(n,d2a) |(n,d2\ :math:`\alpha`\ ) reaction rate. Units are | - | |reactions per source particle. | - +----------------------+---------------------------------------------------+ - |(n,pd) |(n,pd) reaction rate. Units are reactions per | - | |source particle. | - +----------------------+---------------------------------------------------+ - |(n,pt) |(n,pt) reaction rate. Units are reactions per | - | |source particle. | - +----------------------+---------------------------------------------------+ - |(n,da) |(n,d\ :math:`\alpha`\ ) reaction rate. Units are | - | |reactions per source particle. | - +----------------------+---------------------------------------------------+ - |*Arbitrary integer* |An arbitrary integer is interpreted to mean the | - | |reaction rate for a reaction with a given ENDF MT | - | |number. Units are reactions per source particle. | - +----------------------+---------------------------------------------------+ .. note:: The ``analog`` estimator is actually identical to the ``collision`` From 0e2db9afee6d9bf35a5b5618e01b67c48b2449b5 Mon Sep 17 00:00:00 2001 From: "wbinventor@gmail.com" Date: Thu, 28 Jan 2016 14:42:07 -0500 Subject: [PATCH 13/24] Renamed cross.py to arithmetic.py per suggestion by @paulromano --- openmc/{cross.py => arithmetic.py} | 0 openmc/tallies.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename openmc/{cross.py => arithmetic.py} (100%) diff --git a/openmc/cross.py b/openmc/arithmetic.py similarity index 100% rename from openmc/cross.py rename to openmc/arithmetic.py diff --git a/openmc/tallies.py b/openmc/tallies.py index fb07532a0e..3c4d99c730 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -12,7 +12,7 @@ import sys import numpy as np from openmc import Mesh, Filter, Trigger, Nuclide -from openmc.cross import * +from openmc.arithmetic import * from openmc.filter import _FILTER_TYPES import openmc.checkvalue as cv from openmc.clean_xml import * From 51deaa7cbf4a5bc06bb9ddc0dd2beef830115333 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 28 Jan 2016 15:56:28 -0600 Subject: [PATCH 14/24] Prevent segfault when user specifies '18' on tally scores --- src/input_xml.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/input_xml.F90 b/src/input_xml.F90 index ec8a8a5a15..df9d28e13e 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -3247,7 +3247,7 @@ contains call fatal_error("Cannot tally absorption rate with an outgoing & &energy filter.") end if - case ('fission') + case ('fission', '18') t % score_bins(j) = SCORE_FISSION if (t % find_filter(FILTER_ENERGYOUT) > 0) then call fatal_error("Cannot tally fission rate with an outgoing & From 26c5e5e66b52c2768a6639c52745f2ca8d4e0533 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 29 Jan 2016 17:06:58 -0600 Subject: [PATCH 15/24] Fix spacing around % as pointed out by @wbinventor --- src/physics.F90 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/physics.F90 b/src/physics.F90 index c6ecf4fe66..da2682ebf7 100644 --- a/src/physics.F90 +++ b/src/physics.F90 @@ -94,7 +94,7 @@ contains call create_fission_sites(p, i_nuclide, i_reaction, fission_bank, n_bank) elseif (run_mode == MODE_FIXEDSOURCE) then call create_fission_sites(p, i_nuclide, i_reaction, & - p%secondary_bank, p%n_secondary) + p % secondary_bank, p % n_secondary) end if end if @@ -1174,7 +1174,8 @@ contains ! Sample secondary energy distribution for fission reaction and set energy ! in fission bank - bank_array(i) % E = sample_fission_energy(nuc, nuc%reactions(i_reaction), p) + bank_array(i) % E = sample_fission_energy(nuc, & + nuc % reactions(i_reaction), p) ! Set the delayed group of the neutron bank_array(i) % delayed_group = p % delayed_group From c746d7a9faea3de7641bc4b0a08268fdd66569d6 Mon Sep 17 00:00:00 2001 From: "wbinventor@gmail.com" Date: Sat, 30 Jan 2016 11:44:54 -0500 Subject: [PATCH 16/24] Fixed issue with 3D lattice distribcell offsets --- openmc/summary.py | 1 - openmc/universe.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/openmc/summary.py b/openmc/summary.py index eb14d3bb81..29c30c2936 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -368,7 +368,6 @@ class Summary(object): lattice.universes = universes if offsets is not None: - offsets = np.swapaxes(offsets, 0, 2) lattice.offsets = offsets # Add the Lattice to the global dictionary of all Lattices diff --git a/openmc/universe.py b/openmc/universe.py index 237ddce1f7..319acc3302 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -1101,8 +1101,8 @@ class RectLattice(Lattice): # For 3D Lattices else: - offset = self._offsets[i[1]-1, i[2]-1, i[3]-1, distribcell_index-1] - offset += self._universes[i[1]-1][i[2]-1][i[3]-1].get_cell_instance( + offset = self._offsets[i[3]-1, i[2]-1, i[1]-1, distribcell_index-1] + offset += self._universes[i[3]-1][i[2]-1][i[1]-1].get_cell_instance( path, distribcell_index) return offset From 1bd815c52966c9285881d8c6ebca313dcac6c563 Mon Sep 17 00:00:00 2001 From: "wbinventor@gmail.com" Date: Sat, 30 Jan 2016 13:57:06 -0500 Subject: [PATCH 17/24] Fixed distribcell offsets for 2D lattices --- openmc/summary.py | 1 + openmc/universe.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/openmc/summary.py b/openmc/summary.py index 29c30c2936..3e10f8edbd 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -367,6 +367,7 @@ class Summary(object): # Set the universes for the lattice lattice.universes = universes + # Set the distribcell offsets for the lattice if offsets is not None: lattice.offsets = offsets diff --git a/openmc/universe.py b/openmc/universe.py index 319acc3302..74c438615c 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -1095,7 +1095,7 @@ class RectLattice(Lattice): # For 2D Lattices if len(self._dimension) == 2: - offset = self._offsets[i[1]-1, i[2]-1, 0, distribcell_index-1] + offset = self._offsets[i[3]-1, i[2]-1, i[1]-1, distribcell_index-1] offset += self._universes[i[1]-1][i[2]-1].get_cell_instance(path, distribcell_index) From fb0e166e1cd78caad2304701c525c528ae05967f Mon Sep 17 00:00:00 2001 From: "wbinventor@gmail.com" Date: Sat, 30 Jan 2016 15:06:55 -0500 Subject: [PATCH 18/24] Fixed issue with double subdomain-avg MGXS --- openmc/arithmetic.py | 3 ++- openmc/mgxs/library.py | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/openmc/arithmetic.py b/openmc/arithmetic.py index 65e12c5d27..8574c4873e 100644 --- a/openmc/arithmetic.py +++ b/openmc/arithmetic.py @@ -823,7 +823,8 @@ class AggregateFilter(object): """ - if filter_bin not in self.bins: + if filter_bin not in self.bins and \ + filter_bin != self._aggregate_filter.bins: msg = 'Unable to get the bin index for AggregateFilter since ' \ '"{0}" is not one of the bins'.format(filter_bin) raise ValueError(msg) diff --git a/openmc/mgxs/library.py b/openmc/mgxs/library.py index 4b8d8a9149..e87b4bdaef 100644 --- a/openmc/mgxs/library.py +++ b/openmc/mgxs/library.py @@ -568,8 +568,9 @@ class Library(object): for domain in self.domains: for mgxs_type in self.mgxs_types: mgxs = subdomain_avg_library.get_mgxs(domain, mgxs_type) - avg_mgxs = mgxs.get_subdomain_avg_xs() - subdomain_avg_library.all_mgxs[domain.id][mgxs_type] = avg_mgxs + if mgxs.domain_type == 'distribcell': + avg_mgxs = mgxs.get_subdomain_avg_xs() + subdomain_avg_library.all_mgxs[domain.id][mgxs_type] = avg_mgxs return subdomain_avg_library From cc571091a3709452d3f4ae9dafac5554c4a5df73 Mon Sep 17 00:00:00 2001 From: "wbinventor@gmail.com" Date: Sun, 31 Jan 2016 17:47:21 -0500 Subject: [PATCH 19/24] Hotfix for OpenMC-OpenCG lattice conversions with y index reversal for OpenCG --- openmc/opencg_compatible.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openmc/opencg_compatible.py b/openmc/opencg_compatible.py index 0bda48c160..a5573d9eb4 100644 --- a/openmc/opencg_compatible.py +++ b/openmc/opencg_compatible.py @@ -922,6 +922,9 @@ def get_opencg_lattice(openmc_lattice): universe_id = universes[z][y][x].id universe_array[z][y][x] = unique_universes[universe_id] + # Reverse y-dimension in array to match ordering in OpenCG + universe_array = universe_array[:, ::-1, :] + opencg_lattice = opencg.Lattice(lattice_id, name) opencg_lattice.dimension = dimension opencg_lattice.width = pitch From 55f5fa18a3b0d3e3a94eaa2df3d423dfbea427c9 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 1 Feb 2016 12:58:15 -0600 Subject: [PATCH 20/24] Fix CSS override for RTD documentation builds --- docs/source/conf.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 65db07b25e..6ca551a431 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -154,7 +154,8 @@ html_title = "OpenMC Documentation" # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] -html_context = {'css_files': ['_static/theme_overrides.css']} +def setup(app): + app.add_stylesheet('theme_overrides.css') # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. From ec05e52089cdc8506db4d09cfd253381db2959c1 Mon Sep 17 00:00:00 2001 From: "wbinventor@gmail.com" Date: Mon, 1 Feb 2016 15:56:40 -0500 Subject: [PATCH 21/24] Fixed issue in Pandas DataFrame compatibility with OpenCG lattice indexing --- openmc/filter.py | 4 +++- openmc/opencg_compatible.py | 3 --- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/openmc/filter.py b/openmc/filter.py index a0c777fa07..54814a6b6f 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -673,9 +673,11 @@ class Filter(object): # Assign entry to Lattice Multi-index column else: + # Reverse y index per lattice ordering in OpenCG level_dict[lat_id_key][offset] = coords._lattice._id level_dict[lat_x_key][offset] = coords._lat_x - level_dict[lat_y_key][offset] = coords._lat_y + level_dict[lat_y_key][offset] = \ + coords._lattice.dimension[1] - coords._lat_y - 1 level_dict[lat_z_key][offset] = coords._lat_z # Move to next node in LocalCoords linked list diff --git a/openmc/opencg_compatible.py b/openmc/opencg_compatible.py index a5573d9eb4..0bda48c160 100644 --- a/openmc/opencg_compatible.py +++ b/openmc/opencg_compatible.py @@ -922,9 +922,6 @@ def get_opencg_lattice(openmc_lattice): universe_id = universes[z][y][x].id universe_array[z][y][x] = unique_universes[universe_id] - # Reverse y-dimension in array to match ordering in OpenCG - universe_array = universe_array[:, ::-1, :] - opencg_lattice = opencg.Lattice(lattice_id, name) opencg_lattice.dimension = dimension opencg_lattice.width = pitch From e413bf30e5f6437ac3a48f78ede9ed2a834a8050 Mon Sep 17 00:00:00 2001 From: "wbinventor@gmail.com" Date: Mon, 1 Feb 2016 19:24:43 -0500 Subject: [PATCH 22/24] Fixed issue with discrepancy in indexing of y-dimension in lattice universes and offsets --- openmc/summary.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/summary.py b/openmc/summary.py index 3e10f8edbd..d22e367c95 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -369,7 +369,7 @@ class Summary(object): # Set the distribcell offsets for the lattice if offsets is not None: - lattice.offsets = offsets + lattice.offsets = offsets[:, ::-1, :] # Add the Lattice to the global dictionary of all Lattices self.lattices[index] = lattice From a62dc7868f26ffcbcc8fc78129ec760257c6bc15 Mon Sep 17 00:00:00 2001 From: "wbinventor@gmail.com" Date: Tue, 2 Feb 2016 15:53:27 -0500 Subject: [PATCH 23/24] Added test for distribcell tallies in an asymmetric lattice --- tests/test_asymmetric_lattice/inputs_true.dat | 1 + .../test_asymmetric_lattice/results_true.dat | 1 + .../test_asymmetric_lattice.py | 127 ++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 tests/test_asymmetric_lattice/inputs_true.dat create mode 100644 tests/test_asymmetric_lattice/results_true.dat create mode 100644 tests/test_asymmetric_lattice/test_asymmetric_lattice.py diff --git a/tests/test_asymmetric_lattice/inputs_true.dat b/tests/test_asymmetric_lattice/inputs_true.dat new file mode 100644 index 0000000000..70073c6bd2 --- /dev/null +++ b/tests/test_asymmetric_lattice/inputs_true.dat @@ -0,0 +1 @@ +dd39c0ae6327e6e74cb077d56e37c112611b95c4c10d96203e672b3e7f928211cc991ec7ebbf9eeadabd968dcdcb651b250233169b62d43ef6994ab9a46cb34a \ No newline at end of file diff --git a/tests/test_asymmetric_lattice/results_true.dat b/tests/test_asymmetric_lattice/results_true.dat new file mode 100644 index 0000000000..d809e6409d --- /dev/null +++ b/tests/test_asymmetric_lattice/results_true.dat @@ -0,0 +1 @@ +7e75ad5b7979e65e52ce564bfbd8fac819013ef8ba35fe184569b452dd9a1ba98d267b6e33d357fdd1c943f201125ff8a4f8601147b87036525870528063dcae \ No newline at end of file diff --git a/tests/test_asymmetric_lattice/test_asymmetric_lattice.py b/tests/test_asymmetric_lattice/test_asymmetric_lattice.py new file mode 100644 index 0000000000..7b83a590ef --- /dev/null +++ b/tests/test_asymmetric_lattice/test_asymmetric_lattice.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python + +import os +import sys +import glob +import hashlib +sys.path.insert(0, os.pardir) +from testing_harness import PyAPITestHarness +import openmc +from openmc.source import Source +from openmc.stats import Box + + +class AsymmetricLatticeTestHarness(PyAPITestHarness): + + def _build_inputs(self): + """Build an axis-asymmetric lattice of fuel assemblies""" + + # Build full core geometry from underlying input set + self._input_set.build_default_materials_and_geometry() + + # Extract all universes from the full core geometry + geometry = self._input_set.geometry.geometry + all_univs = geometry.get_all_universes() + print(all_univs.keys()) + + # Extract universes encapsulating fuel and water assemblies + water = all_univs[7] + fuel = all_univs[8] + + # Construct a 3x3 lattice of fuel assemblies + core_lat = openmc.RectLattice(name='3x3 Core Lattice', lattice_id=202) + core_lat.dimension = (3, 3) + core_lat.lower_left = (-32.13, -32.13) + core_lat.pitch = (21.42, 21.42) + core_lat.universes = [[fuel, water, water], + [fuel, fuel, fuel], + [water, water, water]] + + # Create bounding surfaces + min_x = openmc.XPlane(x0=-32.13, boundary_type='reflective') + max_x = openmc.XPlane(x0=+32.13, boundary_type='reflective') + min_y = openmc.YPlane(y0=-32.13, boundary_type='reflective') + max_y = openmc.YPlane(y0=+32.13, boundary_type='reflective') + min_z = openmc.ZPlane(z0=0, boundary_type='reflective') + max_z = openmc.ZPlane(z0=+32.13, boundary_type='reflective') + + # Define root universe + root_univ = openmc.Universe(universe_id=0, name='root universe') + root_cell = openmc.Cell(cell_id=1) + root_cell.region = +min_x & -max_x & +min_y & -max_y & +min_z & -max_z + root_cell.fill = core_lat + root_univ.add_cell(root_cell) + + # Over-ride geometry in the input set with this 3x3 lattice + self._input_set.geometry.geometry.root_universe = root_univ + + # Initialize a "distribcell" filter for the cold fuel pin cell + distrib_filter = openmc.Filter(type='distribcell', bins=[27]) + + # Initialize the tallies + tally = openmc.Tally(name='distribcell tally', tally_id=27) + tally.add_filter(distrib_filter) + tally.add_score('nu-fission') + + # Initialize the tallies file + tallies_file = openmc.TalliesFile() + tallies_file.add_tally(tally) + + # Assign the tallies file to the input set + self._input_set.tallies = tallies_file + + # Specify summary output and correct source sampling box + self._input_set.build_default_settings() + self._input_set.settings.output = {'summary': True} + self._input_set.settings.source = Source(space=Box( + [0, 0, 0], [32.13, 32.13, 32.13])) + + # Write input XML files + self._input_set.export() + + def _get_results(self, hash_output=True): + """Digest info in statepoint and summary and return as a string.""" + + # Read the statepoint file + statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0] + sp = openmc.StatePoint(statepoint) + + # Read the summary file + summary = glob.glob(os.path.join(os.getcwd(), 'summary.h5'))[0] + su = openmc.Summary(summary) + sp.link_with_summary(su) + + # Extract the tally of interest + tally = sp.get_tally(name='distribcell tally') + + # Create a string of all mean, std. dev. values for both tallies + outstr = '' + outstr += ', '.join(map(str, tally.mean.flatten())) + '\n' + outstr += ', '.join(map(str, tally.std_dev.flatten())) + '\n' + + # Extract fuel assembly lattices from the summary + all_cells = su.openmc_geometry.get_all_cells() + fuel = all_cells[80].fill + core = all_cells[1].fill + + # Append a string of lattice distribcell offsets to the string + outstr += ', '.join(map(str, fuel.offsets.flatten())) + '\n' + outstr += ', '.join(map(str, core.offsets.flatten())) + '\n' + + # Hash the results if necessary + if hash_output: + sha512 = hashlib.sha512() + sha512.update(outstr.encode('utf-8')) + outstr = sha512.hexdigest() + + return outstr + + def _cleanup(self): + super(AsymmetricLatticeTestHarness, self)._cleanup() + f = os.path.join(os.getcwd(), 'tallies.xml') + if os.path.exists(f): os.remove(f) + + +if __name__ == '__main__': + harness = AsymmetricLatticeTestHarness('statepoint.10.h5', True) + harness.main() From dd18376d3f8de550ff2c0e74ea8fd7d8ee301cf9 Mon Sep 17 00:00:00 2001 From: "wbinventor@gmail.com" Date: Wed, 3 Feb 2016 11:18:50 -0500 Subject: [PATCH 24/24] Made source only fissionable for asymmetric lattice test --- openmc/tallies.py | 2 +- tests/test_asymmetric_lattice/inputs_true.dat | 2 +- tests/test_asymmetric_lattice/results_true.dat | 2 +- .../test_asymmetric_lattice.py | 12 +++++++----- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index 3c4d99c730..3294a1d062 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -2748,7 +2748,7 @@ class Tally(object): bin_indices.append(bin_index) num_bins += 1 - find_filter.bins = set(find_filter.bins[bin_indices]) + find_filter.bins = np.unique(find_filter.bins[bin_indices]) find_filter.num_bins = num_bins # Update the new tally's filter strides diff --git a/tests/test_asymmetric_lattice/inputs_true.dat b/tests/test_asymmetric_lattice/inputs_true.dat index 70073c6bd2..552c8d039e 100644 --- a/tests/test_asymmetric_lattice/inputs_true.dat +++ b/tests/test_asymmetric_lattice/inputs_true.dat @@ -1 +1 @@ -dd39c0ae6327e6e74cb077d56e37c112611b95c4c10d96203e672b3e7f928211cc991ec7ebbf9eeadabd968dcdcb651b250233169b62d43ef6994ab9a46cb34a \ No newline at end of file +fe07eb28fd0dbb56edaecd510f5e8e4db7271e5c9aecf3d880cce92b69872a0aacf825b8e88cd2e9b1ff709f578b269b1835f53cf2561a390062e1e7e03b5276 \ No newline at end of file diff --git a/tests/test_asymmetric_lattice/results_true.dat b/tests/test_asymmetric_lattice/results_true.dat index d809e6409d..0cf2315ea4 100644 --- a/tests/test_asymmetric_lattice/results_true.dat +++ b/tests/test_asymmetric_lattice/results_true.dat @@ -1 +1 @@ -7e75ad5b7979e65e52ce564bfbd8fac819013ef8ba35fe184569b452dd9a1ba98d267b6e33d357fdd1c943f201125ff8a4f8601147b87036525870528063dcae \ No newline at end of file +cea61172ecad5554ef86f52d6adad6ad5e21931cf3d67feb37b8bf9d75e618786f638685e458051d4a39afe1a924fd651cf6674a88cf1f1842fd69cd851e1f17 \ No newline at end of file diff --git a/tests/test_asymmetric_lattice/test_asymmetric_lattice.py b/tests/test_asymmetric_lattice/test_asymmetric_lattice.py index 7b83a590ef..3b9e2029b2 100644 --- a/tests/test_asymmetric_lattice/test_asymmetric_lattice.py +++ b/tests/test_asymmetric_lattice/test_asymmetric_lattice.py @@ -22,7 +22,6 @@ class AsymmetricLatticeTestHarness(PyAPITestHarness): # Extract all universes from the full core geometry geometry = self._input_set.geometry.geometry all_univs = geometry.get_all_universes() - print(all_univs.keys()) # Extract universes encapsulating fuel and water assemblies water = all_univs[7] @@ -55,7 +54,7 @@ class AsymmetricLatticeTestHarness(PyAPITestHarness): # Over-ride geometry in the input set with this 3x3 lattice self._input_set.geometry.geometry.root_universe = root_univ - # Initialize a "distribcell" filter for the cold fuel pin cell + # Initialize a "distribcell" filter for the fuel pin cell distrib_filter = openmc.Filter(type='distribcell', bins=[27]) # Initialize the tallies @@ -70,11 +69,14 @@ class AsymmetricLatticeTestHarness(PyAPITestHarness): # Assign the tallies file to the input set self._input_set.tallies = tallies_file - # Specify summary output and correct source sampling box + self._input_set.build_default_settings() + + # Specify summary output and correct source sampling box + source = Source(space=Box([-32, -32, 0], [32, 32, 32])) + source.only_fissionable = True + self._input_set.settings.source = source self._input_set.settings.output = {'summary': True} - self._input_set.settings.source = Source(space=Box( - [0, 0, 0], [32.13, 32.13, 32.13])) # Write input XML files self._input_set.export()